根据Java Annotation API:
RetentionPolicy.CLASS 注释将由类记录在类文件中 编译器但不需要保留 运行时的VM。
RetentionPolicy.RUNTIME 注释将由类记录在类文件中 编译并在运行时由VM保留 时间,所以他们可能会被阅读 反射性。
我正在寻找“CLASS”保留政策的样本。当我们需要使用此策略而不是RUNTIME策略时。
答案 0 :(得分:17)
CLASS注释用于http://proguard.sourceforge.net等混淆器工具。 例如,注释@KeepName会在您需要更改类名时禁用名称修改,以便能够调用Class.forName()等方法。
答案 1 :(得分:11)
在我当前项目中拥有的所有大量库中。我能找到的唯一示例位于Google Guava库中,例如com.google.common.annotations.GwtCompatible
。
我不确定他们为什么选择这种保留策略 - 可能是工具支持,工具本身读取类文件,而不是通过反射API。不过,我不确定我是否真的看到了这种区别的重点。
答案 2 :(得分:6)
在进行字节代码级后处理时,RetentionPolicy.CLASS非常有用。
示例:
https://github.com/thesmythgroup/DroidCook/blob/master/src/org/tsg/android/api/Annotations.java
答案 3 :(得分:1)
最小例子
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;
}
如果我们在带注释的类上使用javap
,我们会看到Retention.CLASS
带注释的类获得RuntimeInvisible类属性:
#14 = Utf8 LRetentionClass;
[...]
RuntimeInvisibleAnnotations:
0: #14()
而Retention.RUNTIME
注释获得RuntimeVisible类属性:
#14 = Utf8 LRetentionRuntime;
[...]
RuntimeVisibleAnnotations:
0: #14()
因此,字节码中的两种情况都会出现信息。
因此,Runtime.CLASS
可用于将任意元数据与字节码操作工具可以使用的类相关联,而不会干扰运行时可见行为。