不同的保留政策如何影响我的注释?


175

以明确的方式有谁能解释之间的实际差别java.lang.annotation.RetentionPolicy常数SOURCECLASSRUNTIME

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



是的,我已经阅读过,但是在实践中我不理解它是如何工作的。实际上,如果我尝试使用“ this statement”:“”“”注释将由编译器记录在类文件中,但在运行时无需由VM保留。“”,然后打开一个反编译的类,在其中放置了带有保留策略CLASS的注释,我什么也没找到……
xdevel2000 2010年

2
然后,您的反编译器似乎不支持注释。jd-gui工作正常。
musiKk 2010年

谢谢,问题是我的反编译器dj和jad ... jd-gui给我看!
xdevel2000

Answers:


209
  • RetentionPolicy.SOURCE:在编译期间丢弃。这些注释在编译完成后没有任何意义,因此它们不会写入字节码。
    范例:@Override@SuppressWarnings

  • RetentionPolicy.CLASS:在上课时放弃。在进行字节码级后处理时很有用。令人惊讶的是,这是默认设置。

  • RetentionPolicy.RUNTIME: 不要丢弃。注释应可在运行时反射。例:@Deprecated

来源: 旧的URL现在 已死hunter_meta,并替换为hunter-meta-2-098036。万一出现这种情况,我将上传页面图像。

图像(右键单击并选择“在新选项卡/窗口中打开图像”) Oracle网站的屏幕截图


1
感谢您的报价,这里最有趣的是用例RetentionPolicy.CLASS
Max

1
您能解释一下为什么RetentionPolicy.class有趣/令人惊讶的是默认值吗?
sudocoder 2015年

1
@sudocoder-请参阅以下链接:stackoverflow.com/a/5971247/373861stackoverflow.com/a/3849602/373861。我相信字节码检测需要此特定策略。虽然我自己从未使用过它。
Favonius

最后,它说在本系列的下一篇文章中,我将展示如何增强Java的反射功能,以帮助您在运行时发现注释,以及“注释处理工具”“ apt”如何使您在构建时使用注释。,本文在哪里?
Sushant

@Sushant:好吧,我不确定它在哪里。尽管apt已弃用,请参考此docs.oracle.com/javase/7/docs/technotes/guides/apt/…。为了使用反射来发现注释,Internet上有多个教程。你可以寻找到启动java.lang.Class::getAnno*,并在类似的方法java.lang.reflect.Methodjava.lang.reflect.Field
Favonius

57

根据您对类反编译的评论,我认为这应该起作用:

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

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

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


是的,我也是这么想的,但是在反编译类中什么都不存在!!!因此,我很困惑...我将尝试使用javap工具检查类文件
xdevel2000 2010年

javap什么都不会返回,然后放在哪里?
xdevel2000

1
是否有RetentionPolicy.CLASS用例?
拉胡尔

20

最小的可运行示例

语言等级

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上的示例供您使用。


那么,您知道Runtime.SOURCE和Runtime.CLASS的用途是什么?
Praveen Kamath

@PraveenKamath我不知道它们有用的任何示例。仅当您正在执行大多数开发人员从未使用过的较低级JVM时,才可能发生。让我知道您是否找到适合他们的应用程序。
西罗Santilli郝海东冠状病六四事件法轮功

5

保留策略:保留策略确定在什么时候丢弃注释。使用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.

0
  • CLASS :注释由编译器记录在类文件中,但在运行时VM无需保留。
  • RUNTIME :注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取它们。
  • 消息来源 :注释将被编译器丢弃。

甲骨文文档

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.