RetentionPolicy.CLASS和RetentionPolicy.RUNTIME的区别

我们知道注解的RetentionPolicy有三种类型:

(1)RetentionPolicy.SOURCE:只在编译时能被感知,不会在class文件出现

(2)RetentionPolicy.CLASS:会被编译进class文件,但不会在虚拟机运行时感知

(3)RetentionPolicy.RUNTIME:是在运行时也可以被感知到

RetentionPolicy.SOURCE和RetentionPolicy.RUNTIME都比较好理解,接触的也比较多。比如lombok的注解基本都是RetentionPolicy.SOURCE,用于在编译成class文件时动态生成代码,在class文件看不到对应注解存在。而我们大部分写的应用程序注解则大部分是PetentionPolicy.RUNTIME,比如使用Spring AOP时定义运行时注解,提供额外的切面信息。

但RetentionPolicy.CLASS的就很少了,那么它是做什么的呢?

首先我们来自定义一个RetentionPolicy.CLASS的注解:

这里定义了一个RetentionPolicyForClass注解类,在UserInfo类中使用,然后在尝试在运行时获取,我们发现idea会提示问题:Annotation 'RetentionPolicyForClass.class' is not retained for reflective access。注解不能通过反射获取,如果我们把RetentionPolicyForClass的Retention改成Runtime,test就能正常获取了,value是UserInfo类中设置的"userinfo"。实际运行,test返回的是null,确实在运行时获取注解信息。

然后查看UserInfo的class文件:注解信息在class文件中是存在的

所以我们在运行时是无法获取对应注解的信息的,那么它有什么用的。根据类加载的过程,加载需要经过加载,校验,准备,解析,初始化,使用,卸载,这七个步骤,在加载的时候就是把class文件加载到虚拟机,那么这时候虚拟机是能从class文件中感知到注解的存在的,那么就可以在连接阶段(校验,准备,解析)阶段根据信息进行一些操作,个人猜测大概率是给虚拟机底层使用的。如果大家有知道具体使用的,欢迎评论区交流^_^!

当一个自定义注解标记为 `@Retention(RetentionPolicy.CLASS)` 时,它会在编译后的字节码中保留,但在运行时不可见。我们可以通过反射来获取注解并执行一些操作。 下面是一个简单的示例: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.CLASS) @interface MyAnnotation { String value(); } public class MyClass { @MyAnnotation("Hello") public void myMethod() { // do something } } public class Main { public static void main(String[] args) throws NoSuchMethodException { MyClass obj = new MyClass(); // 使用反射获取方法上的注解 Method method = MyClass.class.getMethod("myMethod"); MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); if (annotation != null) { String value = annotation.value(); System.out.println("Value: " + value); // 输出:Value: Hello } } } ``` 在这个例子中,`MyAnnotation` 自定义注解被标记为 `@Retention(RetentionPolicy.CLASS)`。我们通过反射获取 `myMethod` 方法上的注解,并输出注解中的值。 而当一个自定义注解标记为 `@Retention(RetentionPolicy.RUNTIME)` 时,它会在运行时保留,并可以通过反射来获取和处理。 下面是一个简单的示例: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation { String value(); } public class MyClass { @MyAnnotation("Hello") public void myMethod() { // do something } } public class Main { public static void main(String[] args) throws NoSuchMethodException { MyClass obj = new MyClass(); // 使用反射获取方法上的注解 Method method = MyClass.class.getMethod("myMethod"); MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); if (annotation != null) { String value = annotation.value(); System.out.println("Value: " + value); // 输出:Value: Hello } } } ``` 在这个例子中,`MyAnnotation` 自定义注解被标记为 `@Retention(RetentionPolicy.RUNTIME)`。我们同样通过反射获取 `myMethod` 方法上的注解,并输出注解中的值。 这两个例子中的注解都可以通过反射访问,并根据需要执行相应的操作。区别在于 `@Retention(RetentionPolicy.CLASS)` 注解在运行时不可见,只能在编译后的字节码中通过反射来访问,而 `@Retention(RetentionPolicy.RUNTIME)` 注解在运行时可见,可以直接通过反射来访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值