任何人都可以清楚地解释java.lang.annotation.RetentionPolicy
常数SOURCE
,CLASS
和RUNTIME
之间的实际差异吗?
我也不完全确定“保留注释”这个短语是什么意思。
RetentionPolicy.SOURCE
:在编译期间丢弃。编译完成后,这些注释没有任何意义,因此它们不会写入字节码。 示例:@Override
,@SuppressWarnings
RetentionPolicy.CLASS
:在课堂加载期间丢弃。在进行字节码级后处理时很有用。有点令人惊讶的是,这是默认值。RetentionPolicy.RUNTIME
:不要丢弃。注释应该可以在运行时进行反射。示例:@Deprecated
来源:现在旧网址已经死了 hunter_meta 并用hunter-meta-2-098036取代。如果这种情况发生了变化,我会上传页面的图像。
Image(右键单击并选择'在新标签/窗口中打开图像')
根据你对类反编译的评论,我认为它应该如何工作:
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
没有得到任何注释。
RetentionPolicy.SOURCE
:注释将在程序的源代码中提供,它既不在.class文件中,也不在运行时可用。由编译器使用。
RetentionPolicy.CLASS
:注释将在.class文件中,但在运行时不可用。由字节代码操作工具(如ASM)使用来执行修改
RetentionPolicy.RUNTIME
:注释可以在.class文件和运行时获得,通过getAnnotations()
通过java反射进行检查。
保留策略:保留策略确定放弃注释的位置。
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。