注解和反射

104 阅读4分钟

注解

什么是注解

df29b25756b863496410d0389447709.jpg

package zhujie;

public class TestDome01 {
    // @Override 重写的注解
    @Override
    public String toString() {
        return super.toString();
    }
}

内置注解

9cd8eb6bcf9b3741ef26099b877b4d4.jpg

package zhujie;

import java.util.ArrayList;
import java.util.List;

public class TestDome01 {
    // @Override 重写的注解
    @Override
    public String toString() {
        return super.toString();
    }

    // 不推荐程序员使用,但是可以使用,或存在更好的方式
    @Deprecated
    public static void test(){
        System.out.println("Deprecated");
    }

    @SuppressWarnings("all")
    public void test2(){
        List list = new ArrayList();
    }

    public static void main(String[] args) {
        test();
    }
}

元注解

1c700f1369bd8af7350532529dd401f.jpg

1.Target

dd2841d8848ab0edc7e22d4815acf85.jpg

package zhujie;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

// 测试元注解
@MyAnnotation
public class TestDome02 {
    @MyAnnotation
    public void test(){
        
    }
    
}
// 定义一个注解
@Target(value ={ElementType.METHOD,ElementType.TYPE}) // 作用域
 @interface MyAnnotation{
    
}

自定义注解

b5e6849bad534bf8dcb845097433582.jpg

package zhujie;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 自定义注解
public class TestDome03 {
    // 注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation2(name = "zcw")
    public void test(){

    }

}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    // 注解的参数:参数类型 + 参数名();
    String name() default "";
    int age() default 0;
    int id() default -1; // 如果默认值为-1,代表不存在
}

反射

585d6340038a21872f3c4fcbc118e2c.jpg 优点 :可以实现动态创建对象和编译,体现出很大的灵活性
缺点 :对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的需求。这类操作总是慢于直接执行相同的操作。

获取反射对象

package fanshe;
// 什么家反射
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 通过反射获取类的class对象
        Class c1 = Class.forName("fanshe.User");
        System.out.println(c1);

        Class c2 = Class.forName("fanshe.User");
        Class c3 = Class.forName("fanshe.User");
        // 一个类在内存中只会存在一个class对象
        // 一个类在加载后,整个类的结构都会封装在Class对象中。
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
    }
}

// 实体类:pojo , entity
class User{
    private String name;
    private int id;
    private int age;

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

获得class的几种方法

a808637366aedd975ed39d9625d8ceb.jpg

package fanshe;
// 测试class类的创建方式有哪些
public class Test03 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是"+person.name);

        // 方法一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        // 方式二:forname获得
        Class c2 = Class.forName("fanshe.Student");
        System.out.println(c2.hashCode());

        // 方式三:通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        // 方式四:基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;

        // 获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}
class Person{
    String name;

    public Person(String name) {
        this.name = name;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                '}';
    }
}
class Student extends Person {
    public Student() {
        this.name = "学生";
    }
}
    class Teacher extends Person {
        public Teacher() {
            this.name = "老师";
        }
}

所有类型的Class对象

754ba1f038ed53bde3753f74895a913.jpg

package fanshe;

import java.lang.annotation.ElementType;

// 所有类型的Class
public class TestDome04 {
    public static void main(String[] args) {
        Class c1 = Object.class; // 类
        Class c2 = Comparable.class; // 接口
        Class c3 = String[].class; // 数组
        Class c4 = Override.class; // 注解
        Class c5 = ElementType.class; // 枚举
        Class c6 = void.class;// void

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
    }
}

类加载内存

类的加载

5a8ec2725127d969a1ea0e52b0d912b.jpg

0f41539c6c5844f2db22982e5a777eb.jpg

类的初始化

c02dff3ddcd7672f3ff36e0b4a2b1be.jpg

package fanshe;

// 测试类什么时候会初始化
public class Test06 {
    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        // 1.主动引用
        Son son = new Son(); // Main,Father,Son

        // 2.反射也会主动引用
        Class.forName("fanshe.Son");// Main,Father,Son

        // 不会产生类的引用的方法
        System.out.println(Son.b);// Main,Father
        System.out.println(Son.M); // Main
    }
}

class Father{
    static  int b = 2;
    static {
        System.out.println("父类被加载");
    }
}
class Son extends Father{
    static {
        System.out.println("子类被加载");
        m = 300;
    }
    static int m = 100;
    static final int M = 1;
}

类加载器

a0bd6697f84f73ec094e2a6acf80ba2.jpg

获取类运行时的完整结构

008137cbf19360480b7076b7bf78ce8.jpg

package fanshe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("fanshe.User");

        // 获得类的名字
        System.out.println(c1.getName()); // 活的包名+类名
        System.out.println(c1.getSimpleName()); // 活动类名

        // 获得类的属性
        Field[] fields = c1.getFields(); // 只能找到public属性
        fields = c1.getDeclaredFields(); // 找到全部属性
        for (Field field : fields){
            System.out.println(field);
        }

        // 获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        // 获得类的方法
        Method[] methods = c1.getMethods(); // 获得本类及其父类的public方法
        for (Method method : methods) {
            System.out.println("正常的"+method);
        }
        methods = c1.getDeclaredMethods(); // 获得本类的方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods"+method);
        }

        // 获得制定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        // 获得指定构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(declaredConstructor);
    }
}

动态创建对象执行方法

5452a2b7dd9f4d5cb5129517041d18b.jpg

package fanshe;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 获得Class对象
        Class c1 = Class.forName("fanshe.User");

        // 构造一个对象
        User user = (User) c1.newInstance(); // 本质是调用了无参构造器
        System.out.println(user);

        // 通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User) constructor.newInstance("zcw", 001, 18);
        System.out.println(user2);

        // 通过反射调用普通方法
        User user3 = (User) c1.getDeclaredConstructor().newInstance();
        // 通过反射获取方法
        // invoke : 激活 ,(对象,“方法的值”)
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user3,"zcw");
        System.out.println(user3.getName());
    }
}

性能对比分析

830cc9c84622dcc0634bd13ebcbde25.jpg