@Retention注解简单说明
是什么:
@Retention是用来修饰注解的,它定义了该注解被保留时间的长短,是注解的注解,是JAVA元注解之一。
为什么:
注解有不同的生命周期,按不同的生命周期可分为3类。
1.某些注解只保存在源文件中,当.java文件翻译成.class文件,该注解就被遗弃。
2.某些注解只保留到.class文件,但JVM加载.class文件时,该注解会被遗弃。
3.某些注解在.class被装载时将被读取,在程序运行期间,将一直保留。
这三种生命周期分别对应于三种状态。
1..java文件
2..class文件
3.内存中的字节码
而@Retention的作用就是用于描述注解的生命周期。
怎么用:
首先看一下@Retention的源码:
它只有一个属性值,RetentionPolicy的对象value。
这是一个enum类型,里面只有3个值SOURCE,CLASS,RUNTIME。@Retention就是靠这3个值来描述注解的生命周期。
它们相对应的生命周期以及举例:
RetentionPolicy | 对应的生命周期 | 用法 | 举例 |
---|---|---|---|
SOURCE | 只保存在源文件中,当.java文件翻译成.class文件,该注解就被遗弃。 | 一般用于运行前的检查 | @Override,@SupressWarnings |
CLASS | 只保留到.class文件,但JVM加载.class文件时,该注解会被遗弃。 | 在编译时进行一些预处理操作 | @ButterKnife(Android) |
RUNTIME | 在.class被装载时将被读取,在程序运行期间,将一直保留。 | 在运行时去动态获取注解信息 | @Deprecated |
周期长度是SOURCE < CLASS < RUNTIME,所以前者能作用到的地方后者一定能作用到
@Override是让编译器检查当前方法是否在覆盖父类方法,@SupressWarnings也只是为了抑制代码警告,在代码编译后就都没有什么作用,因此不需要写入.class文件。
@ButterKnife会在编译时生成辅助代码,所以用RetentionPolicy.CLASS修饰。
RetentionPolicy.CLASS是默认生命周期,没有被@Retention修饰的注解的生命周期都是这种策略。
RetentionPolicy.RUNTIME修饰的注解处理器可以通过反射获取该注解的属性值,从而做一些运行时的逻辑处理。
关于@Deprecated的额外话
从上表可知,@Deprecated是用RetentionPolicy.RUNTIME标记的,处理器是可以通过反射获取@Deprecated的属性的。
但是去看源码,@Deprecated什么属性都没有,处理器反射获得属性的行为也就没什么必要。
于是有了一个想法,为什么一定要RUNTIME,为什么不用SOURCE或者CLASS呢?
@Deprecated是警告标记的一些方法或类过时或者危险,有更好的可以替代,但标记的方法或者类依旧可以用。
这样像@Override和@SupressWarnings一样编译器检查不就行了,为什么还需要设置为RUNTIME。
为此,查询了stackoverflow,这是投票最高的回答:
There are some frameworks and tools that instantiate objects to work with them.
For example, many JavaBean UI editors create instances of the beans and interact with them as the user manipulates the UI they're designing.
Having the @Deprecated annotation available at runtime allows tools such as this to flag deprecated methods, events, properties for the user.
“一些框架或者工具可以实例化对象来使用它们。
例如,许多JavaBean UI编辑器创建bean的实例,并在用户操纵他们正在设计的UI时与它们进行交互。
通过在运行时使用@Deprecated注解,可以使用诸如此类的工具为用户标记不赞成使用的方法,事件和属性。”
恕我愚笨,想不出例子来验证这句话,如果能解释这句话或者有更好的想法请赐教。