Java Annotations – 寻找RetentionPolicy.CLASS的示例

根据Java Annotation API:

  • RetentionPolicy.CLASS注释将由编译器记录在类文件中,但在运行时不需要由VM保留。

  • RetentionPolicy.RUNTIME注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以reflection性地读取它们。

我正在寻找“CLASS”保留政策的样本。 当我们需要使用此策略而不是RUNTIME策略时。

在我当前项目中拥有的所有大量库中。 我能找到的唯一例子是Google Guava库,例如com.google.common.annotations.GwtCompatible

我不确定他们为什么选择这种保留策略 – 也许是为了工具支持,工具本身读取类文件,而不是通过reflectionAPI。 不过,我不确定我是否真的看到了这种区别。

CLASS注释用于混淆器工具,如http://proguard.sourceforge.net 。 例如,注释@KeepName会在您需要更改类名时禁用名称修改,以便能够调用Class.forName()等方法。

在进行字节代码级后处理时,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; } 

如果我们在带注释的类上使用javap ,我们会看到Retention.CLASS注释的类获取RuntimeInvisible类属性:

 #14 = Utf8 LRetentionClass; [...] RuntimeInvisibleAnnotations: 0: #14() 

Retention.RUNTIME注释获取RuntimeVisible类属性:

 #14 = Utf8 LRetentionRuntime; [...] RuntimeVisibleAnnotations: 0: #14() 

因此信息存在于字节码中的两种情况中。

因此, Runtime.CLASS可用于将任意元数据关联到字节码操作工具可以使用的类,而不会干扰运行时可见行为。

GitHub上的示例供您使用。