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

时间:2010-06-24 07:33:54

标签: java annotations

任何人都可以清楚地解释java.lang.annotation.RetentionPolicy常量SOURCECLASSRUNTIME之间的实际差异吗?

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

7 个答案:

答案 0 :(得分:183)

  
      
  • RetentionPolicy.SOURCE:弃牌期间   编译。这些注释没有   在编译之后有意义   完成了,所以他们不写   字节码。
      示例:@Override@SuppressWarnings

  •   
  • RetentionPolicy.CLASS:弃牌期间   类加载。这样做很有用   字节码级后处理。   有点令人惊讶的是,这就是   默认值。

  •   
  • RetentionPolicy.RUNTIME:不要   丢弃。注释应该是   可用于运行时的反射。   示例:@Deprecated

  •   

<强>来源: 旧的URL现在已经死了 hunter_meta 并替换为hunter-meta-2-098036。如果这种情况发生了变化,我会上传页面图片。

Image(右键单击并选择“在新标签/窗口中打开图片”) Screenshot of Oracle website

答案 1 :(得分:46)

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

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

  • RetentionPolicy.CLASS:出现在反编译的类中,但无法在运行时使用[{1}}

  • 进行反射检查
  • getAnnotations():出现在反编译的类中,可以在运行时使用[{1}}

  • 进行反思检查

答案 2 :(得分:18)

最小可运行示例

语言水平

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没有获得任何注释。

Examples on GitHub让你玩。

答案 3 :(得分:4)

RetentionPolicy.SOURCE:注释将在程序的源代码中提供,它既不在.class文件中,也不在运行时可用。由编译器使用。
RetentionPolicy.CLASS:注释将在.class文件中,但在运行时不可用。由字节码操作工具(如ASM)使用,执行修改
RetentionPolicy.RUNTIME:注释可以在.class文件和运行时获得,通过getAnnotations()的java反射进行检查。

答案 4 :(得分:3)

保留策略:保留策略确定放弃注释的位置。

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.

使用Java的内置注释指定保留策略:@Retention。

答案 5 :(得分:0)

@Retention允许您定义注释的生命周期[About]

RetentionPolicy.SOURCE:仅在编译器使用的源代码中可用。很好的例子是Java世界中的@Override@SuppressWarnings和Android注释中的@IntDef@StringDef

RetentionPolicy.CLASS:仅在.class文件中可用。由一些工具代码生成,操纵,配置等使用。例如ASM framework或Jake Wharton和{{3}的Java AspectJHugo之类的Java AOP范例},来自Fernando Cejas

RetentionPolicy.RUNTIME:在.class文件和运行时可用。您可以通过getAnnotations() Java Reflection API来获取它。例如,匕首2的@Scope注释

答案 6 :(得分:0)

  • CLASS :注释将由编译器记录在类文件中,但不必在运行时由VM保留。
  • 运行时间 :注释由编译器记录在类文件中,并在运行时由VM保留,以便可以通过反射方式读取。
  • 来源 :注释将被编译器丢弃。

Oracle Doc