根据Java Annotation API:
RetentionPolicy.CLASS注释将由编译器记录在类文件中,但在运行时不需要由VM保留.
RetentionPolicy.RUNTIME注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以反射性地读取它们.
我正在寻找"CLASS"保留政策的样本.当我们需要使用此策略而不是RUNTIME策略时.
小智 17
CLASS注释用于混淆器工具,如http://proguard.sourceforge.net.例如,注释@KeepName会在您需要更改类名时禁用名称修改,以便能够调用Class.forName()等方法.
ska*_*man 11
在我当前项目中拥有的所有大量库中.例如,我能找到的唯一例子就是Google Guava库com.google.common.annotations.GwtCompatible.
我不确定他们为什么选择这种保留策略 - 可能是工具支持,工具本身读取类文件,而不是通过反射API.不过,我不确定我是否真的看到了这种区别.
在进行字节代码级后处理时,RetentionPolicy.CLASS非常有用.
示例:
https://github.com/thesmythgroup/DroidCook/blob/master/src/org/tsg/android/api/Annotations.java
http://retroweaver.sourceforge.net/
最小的例子
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}
@Retention(RetentionPolicy.RUNTIME)
@interface RetentionRuntime {}
public static void main(String[] args) {
@RetentionClass
class C {}
assert C.class.getAnnotations().length == 0;
@RetentionRuntime
class D {}
assert D.class.getAnnotations().length == 1;
}
Run Code Online (Sandbox Code Playgroud)
javap如果我们在带注释的类上使用,我们会看到Retention.CLASS带注释的类获得RuntimeInvisible类属性:
#14 = Utf8 LRetentionClass;
[...]
RuntimeInvisibleAnnotations:
0: #14()
Run Code Online (Sandbox Code Playgroud)
而Retention.RUNTIME注释获取RuntimeVisible类属性:
#14 = Utf8 LRetentionRuntime;
[...]
RuntimeVisibleAnnotations:
0: #14()
Run Code Online (Sandbox Code Playgroud)
因此,这两种情况的信息都存在于字节码中。
因此,Runtime.CLASS可用于将任意元数据与字节码操作工具可以使用的类相关联,而不会干扰运行时可见的行为。
GitHub 上的示例供您使用。