不同的 Retention Policy 如何影响注解?

谁能清楚地解释一下java.lang.annotation.RetentionPolicy常量SOURCECLASSRUNTIME之间的实际差异?

我也不太确定短语“保留注释”是什么意思。

68882 次浏览
  • RetentionPolicy.SOURCE:丢弃期间 编译。这些注释没有 编译完成后再做任何有意义的事情 完成,所以它们不会被写入 字节码。< br > 例如:@Override@SuppressWarnings

  • RetentionPolicy.CLASS:丢弃期间 类加载。在做某事时有用 字节码后处理。 有点令人惊讶的是,这是 李违约。< / p > < / >

  • RetentionPolicy.RUNTIME:不允许 丢弃。注释应该是 可用于运行时的反射。 李的例子:@Deprecated < / p > < / >

< >强来源: 旧的URL现在已经死了 hunter_meta并替换为猎人- meta - 2 - 098036。为了防止这种情况发生,我正在上传页面的图像。

图像(右击并选择“在新选项卡/窗口中打开图像”)  Oracle网站截图 < / p >

根据你对类反编译的评论,下面是我认为它应该如何工作:

  • RetentionPolicy.SOURCE:不会出现在反编译类中

  • RetentionPolicy.CLASS:出现在反编译类中,但不能在运行时通过getAnnotations()的反射进行检查

  • RetentionPolicy.RUNTIME:出现在反编译类中,并且可以在运行时通过getAnnotations()的反射进行检查

最小可运行示例

语言水平:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;


@Retention(RetentionPolicy.SOURCE)
@interface RetentionSource {}


@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}


@Retention(RetentionPolicy.RUNTIME)
@interface RetentionRuntime {}


public static void main(String[] args) {
@RetentionSource
class B {}
assert B.class.getAnnotations().length == 0;


@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.SOURCE注释的.class没有得到任何注释。

GitHub上的例子给你玩。

保留策略:保留策略决定注释在什么时候被丢弃。它是使用Java的内置注释:@Retention<一口>[对]< /一口>指定的

1.SOURCE: annotation retained only in the source file and is discarded
during compilation.
2.CLASS: annotation stored in the .class file during compilation,
not available in the run time.
3.RUNTIME: annotation stored in the .class file and available in the run time.
  • < >强类 :注释由编译器记录在类文件中,VM在运行时不需要保留注释
  • < >强运行时 :注释将由编译器记录在类文件中,并由VM在运行时保留,因此它们可以反射地读取
  • < >强源 :注释将被编译器丢弃

Oracle Doc