注解与反射

元注解有四部分组成: 
@Target: 定义注解用在什么范围  ( TYPE,  FIELD,METHOD,PARAMETER, CONSTRUCTOR,LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE)
@Retention :定义注解的生命周期  source—class —runtime.   常定义为 runtime 
@Document : 说明该注解存放在Javadoc中
@Inherited: 说明子类可以继承父类注解 
示例:
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
     String value() default "";
}

注解只有被解析之后才会生效,常见的解析方法有两种:
编译期直接扫描 :编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用@Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。
运行期通过反射处理 :像框架中自带的注解(比如 Spring 框架的 @Value 、@Component)都是通过反射来进行处理的。

 
反射: reflection是java视为动态语言的关键,反射机制允许程序在执行期间获得类的内部信息,并且能够操作对象的内部属性以及方法。
实现反射的方式: 
1.已知道类的全类名 可以通过Class.forName(全类名)  
2.已知道类的实例 可以通过类.getClass()
3.已知道具体的类 可以通过类名.class
示例: 
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private int age;
    private String name;
}

class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //方式一
        Class<?> c1 = Class.forName("com.example.demo.reflection.User");
        System.out.println(c1);

        //方式2
        User user = new User();
        Class<? extends User> c2 = user.getClass();
        System.out.println(c2);

        //方式3
        Class c3 = User.class;
        System.out.println(c3);
        //获得包+类名
        System.out.println(c1.getName());
        //获得类名
        System.out.println(c1.getSimpleName());

        //获得类的属性
        Arrays.stream(c1.getFields()).forEach(field -> System.out.println("获得类属性:" + field));
        //获得私有属性值
        Arrays.stream(c1.getDeclaredFields()).forEach(field -> System.out.println("获得类属性:" + field));
        //获得指定属性值:
        System.out.println(c1.getDeclaredField("name"));

        //获得类的方法:本类以及父类
        Arrays.stream(c1.getMethods()).forEach(method -> System.out.println("获得类方法1:" + method));
        //获得类的所有方法
        Arrays.stream(c1.getDeclaredMethods()).forEach(method -> System.out.println("获得类方法2:" + method));
        //获得指定方法
        System.out.println(c1.getMethod("getName", null));

        //获得构造器
        Arrays.stream(c1.getConstructors()).forEach(constructor -> System.out.println("构造器1:" + constructor));
        Arrays.stream(c1.getDeclaredConstructors()).forEach(constructor -> System.out.println("构造器2:" + constructor));

        //构造一个对象  newInstance 本质上是调用无参构造器
        User user1 = (User) c1.newInstance();
        System.out.println("user1: " + user1);

        //给对象属性赋值
        Method method = c1.getMethod("setName", String.class);
        method.invoke(user1, "李白");
        System.out.println("user1" + user1);

        //通过属性赋值
        Field field = c1.getDeclaredField("name");
        field.setAccessible(true);
        field.set(user1, "张三");
        System.out.println("user1" + user1);

        //获得有参构造器 并赋值
        Constructor constructor = c1.getDeclaredConstructor(int.class, int.class, String.class);
        User user2 = (User) constructor.newInstance(1, 18, "李白");
        System.out.println("user2:" + user2);

    }
}

 

posted @ 2021-12-12 18:09  山阴路的秋天  阅读(43)  评论(0编辑  收藏  举报