注解与反射

注解与反射

自定义注解

@Target 描述的注解可以用在什么地方
@Retention 表示被它所注解的注解在什么地方还有效
@Documented 是否将我们的注解生成在javaDoc文档中
@Inherited 说明子类可以继承父类中的该注解

/**
 * @program: 注解和反射
 * @description: 自定义注解
 * @author: wangj
 * @create: 2021/08/14 20:42
 */
public class Test03 {

    // 注解可以显示赋值,如果没有默认值,我们就必须给注解赋值
    @MyAnnotation2(name="名字",schools={"朝阳小学","朝阳中学"})
    @MyAnnotation3("这这这这")
    public void test(){

    }
}

// 定义一个注解
@Target({ElementType.METHOD,ElementType.TYPE}) //描述的注解可以用在什么地方
@Retention(RetentionPolicy.RUNTIME) //表示被它所注解的注解在什么地方还有效
@Documented // 是否将我们的注解生成在javaDoc文档中
@Inherited  // 说明子类可以继承父类中的该注解
@interface MyAnnotation{
    String name() default "";
    int age() default 0;

    String[] schools();

}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    String value(); // 注解如果只有一个参数,用value(),使用是 value可以省略
}

获得反射对象

一个类在内存中只有一个Class对象

public class Test02 {

    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("com.example.reflection.User");
        Class c2 = Class.forName("com.example.reflection.User");
        Class c3 = Class.forName("com.example.reflection.User");
        Class c4 = Class.forName("com.example.reflection.User");
        System.out.println(c1);

        // 一个类在内存中只有一个Class对象
        // 一个类被加载后,类的整个结构都会被封装在Class对象中
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());

    }
}

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

    public User() {
    }

    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类的几种方式

通过对象获得

对象.getClass

forName获得

Class.forName()

通过类名.class 获得

类名.class

基本内置对象的包装类都有一个Type属性

Class c4 = Integer.TYPE

public class Test03 {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Person person = new Student();
        System.out.println("这个人是:" + person.name);

        //方式一: 通过对象获得
        Class c1 = person.getClass();
        System.out.println("通过<对象.getClass>获得Student Class对象: " + c1.hashCode());

        // 方式二: forName获得
        Class c2 = Class.forName("com.example.reflection.Student");
        System.out.println("通过获得Student Class对象: " + c2.hashCode());

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

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

        System.out.println("通过<包装类的Type属性>,获取Class对象: " + c4);

        // 获取父类类型
        Class c5 = c1.getSuperclass();
        System.out.println("通过获取父类类型: " +c5);

        Teacher teacher = test(Teacher.class);
        System.out.println(teacher);
    }

    public static  T test(Class claZZ) throws InstantiationException, IllegalAccessException {
        return claZZ.newInstance();
    }

}

class Person{
    String name;

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{
    public Student() {
        this.name="学生";
    }
}

class Teacher extends Person{
    public Teacher() {
        this.name="老师";
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

获得类的信息

获得类的名字:

getName() 获得包名 + 类名

getSimpleName() 获得类名

获得类的属性:

getFields() 只能找到public属性

getDeclaredFields() 找到所有属性

获得类的方法:

getMethods() // 获得本类及其父类的全部方法

getDeclaredMethods() // 获得本类的全部方法

获得指定的方法:

getMethod("setName", String.class); // 获得名称为setName,参数为String 的方法

获得指定的构造器:

getConstructors() // 获得public 构造方法

getDeclaredConstructors() // 获得全部 构造方法

获得指定构造器:
getDeclaredConstructor(String.class, Integer.TYPE,int.class) 获得参数为(String ,int,int)的构造方法

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

        // 获得类的名字
        System.out.println(c1.getName()); // 获得包名 + 类名
        System.out.println(c1.getSimpleName()); // 获得类名
        // 获得类的属性
//        Field[] fields = c1.getFields(); //只能找到public属性
//        for (Field field : fields) {
//            System.out.println(field);
//        }

        Field[] fields = c1.getDeclaredFields(); // 找到所有属性
        for (Field field : fields) {
            System.out.println(field);
        }
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        // 获得类的方法
        Method[] methods = c1.getMethods(); // 获得本类及其父类的全部方法
        for (Method method : methods) {
            System.out.println(" getMethods ==>" + 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);

        // 获得指定的构造器
        System.out.println("============================================");
        Constructor[] constructors = c1.getConstructors(); // 获得public 构造方法
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();  // 获得全部 构造方法
        for (Constructor constructor : constructors) {
            System.out.println(" ### " + constructor);
        }
        // 获得指定构造器
        Constructor constructor = c1.getDeclaredConstructor(String.class, Integer.TYPE,int.class);
        System.out.println(constructor);
    }
}

动态创建对象执行方法

Class.newInstance() 调用了类的无参构造器构造一个对象
Constructor.newInstance(Object... var1) 通过构造器创建对象
Method.invokeinvoke(Object var1, Object... var2) 通过反射调用普通方法

能直接操作私有属性,需要关闭程序的安全检测,属性或方法的 setAccessible 方法
Field.setAccessible(true) 关闭java访问安全检查
Field.set(Object var1, Object var2) 通过反射操作属性

public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 获得class对象
        Class c1 = Class.forName("com.example.reflection.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("无伤", 1, 18);
        System.out.println(user2);

        // 通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // 调用(对象,"方法的参数")==> 调用 对象的方法
        setName.invoke(user3,"无敌");
        System.out.println(user3);

        // 通过反射操作属性
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // 不能直接操作私有属性,需要关闭程序的安全检测,属性或方法的 setAccessible 方法
        name.setAccessible(true); //关闭java访问安全检查
        name.set(user4,"无名");
        System.out.println(user4);

    }
}

获取泛型信息

method.getGenericParameterTypes() 获得泛型参数类型

Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments() 获取实际参数类型

Type genericReturnType = method.getGenericReturnType() 获得返回泛型类型

public class Test08 {

    public void test01(Map map, List list){
        System.out.println("test01");
    }

    public Map test02(){
        System.out.println("test01");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {

        System.out.println("==============参数泛型=================");
        Method method= Test08.class.getMethod("test01", Map.class, List.class);
        // 获得泛型参数类型
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(" # " + genericParameterType);
            // 获取实际参数类型
            Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("--" + actualTypeArgument);

            }
        }
        //  获得返回泛型类型
        System.out.println("=============返回值泛型==================");
        method = Test08.class.getMethod("test02", null);
        Type genericReturnType = method.getGenericReturnType();
        System.out.println(genericReturnType);
        // 获取实际参数类型
        Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
        for (Type actualTypeArgument : actualTypeArguments) {
            System.out.println("--" + actualTypeArgument);

        }
    }
}

反射操作注解

通过反射获得注解 class.getAnnotations()

获得指定注解 MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);

获得注解的属性值 String value = myTable.value();

public class Test09 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.example.reflection.Stu");

        // 通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        // 获得注解的value的值
        MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
        String value = myTable.value();
        System.out.println(value);

        // 获得类指定属性的注解
        Field name = c1.getDeclaredField("name");
        MyField myField = name.getAnnotation(MyField.class);
        System.out.println(myField.column());
        System.out.println(myField.type());
        System.out.println(myField.length());

    }

}

@MyTable("db_stu")
class Stu{
    @MyField(column = "db_id",type = "int",length = 10)
    private int id;
    @MyField(column = "db_age",type = "int",length = 10)
    private int age;
    @MyField(column = "db_name",type = "varchar",length = 10)
    private String name;

    public Stu() {
    }

    public Stu(int id, int age, String name) {
        this.id = id;
        this.age = age;
        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;
    }

    public String getName() {
        return name;
    }

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

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


// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTable{
    String value();
}

// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyField{
    String column();
    String type();
    int length();
}

你可能感兴趣的:(注解与反射)