RetentionPolicy CLASS与RUNTIME

问题描述 投票:43回答:3

RetentionPolicy.CLASSRetentionPolicy.RUNTIME有什么实际区别?

看起来两者都记录在字节码中,无论如何都可以在运行时访问它们。

java annotations
3个回答
52
投票

无论如何都可以在运行时访问它们。

这不是javadoc所说的:

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

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

在实践中,我不知道CLASS的任何用例。只有你想以编程方式读取字节码才有用,而不是通过类加载器API,但这是一个非常专业的情况,我不知道为什么你不会只使用RUNTIME

具有讽刺意味的是,CLASS是默认行为。


2
投票

看起来两者都记录在字节码中,无论如何都可以在运行时访问它们。

对于像getAnnotations这样的基本内置注释接口,这是假的。例如。:

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;
}

所以观察RetentionPolicy.CLASS注释的唯一方法是使用字节码解析器。

另一个区别是Retention.CLASS注释类获得RuntimeInvisible类属性,而Retention.RUNTIME注释获得RuntimeVisible类属性。这可以用javap观察到。

Examples on GitHub供你玩。


0
投票

可以从类字节代码访问具有保留策略CLASSRUNTIME的注释。我们需要使用字节代码操作库(例如ASM)来访问字节代码中可用的Annotations。

这里有一个简单的例子 - http://bethecoder.com/applications/tutorials/java/annotations/class-and-runtime-retention-policy.html

© www.soinside.com 2019 - 2024. All rights reserved.