简体   繁体   English

RetentionPolicy CLASS 与 RUNTIME

[英]RetentionPolicy CLASS vs. RUNTIME

What is the practical difference between RetentionPolicy.CLASS and RetentionPolicy.RUNTIME ? RetentionPolicy.CLASSRetentionPolicy.RUNTIME之间的实际区别是什么?

It looks like both are recorded into the bytecode and both may be accessed at the run-time anyway.看起来两者都记录在字节码中,无论如何都可以在运行时访问。

both may be accessed at the run-time anyway.无论如何,两者都可以在运行时访问。

That's not what the javadoc says:这不是javadoc所说的:

RUNTIME: Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively . RUNTIME:注解会被编译器记录在类文件中,并在运行时由VM保留,因此可以反射读取

CLASS: Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time . CLASS:注解将被编译器记录在类文件中,但不需要在运行时由 VM 保留

In practice, I'm not aware of any use-cases for CLASS .实际上,我不知道CLASS的任何用例。 It would only be useful if you wanted to read the bytecode programmatically, as opposed to via the classloader API, but that's a very specialised case, and I don't know why you wouldn't just use RUNTIME .仅当您想以编程方式读取字节码时才有用,而不是通过类加载器 API,但这是一个非常特殊的情况,我不知道您为什么不只使用RUNTIME

Ironically, CLASS is the default behaviour.具有讽刺意味的是, CLASS是默认行为。

It looks like both are recorded into the bytecode and both may be accessed at the run-time anyway.看起来两者都记录在字节码中,无论如何都可以在运行时访问。

False for basic built-in annotation interfaces like getAnnotations .对于像getAnnotations这样的基本内置注解接口是getAnnotations Eg:例如:

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

so the only way to observe a RetentionPolicy.CLASS annotation is by using a bytecode parser.所以观察RetentionPolicy.CLASS注释的唯一方法是使用字节码解析器。

Another difference is that the Retention.CLASS annotated class gets a RuntimeInvisible class attribute, while Retention.RUNTIME annotations get a RuntimeVisible class attribute.另一个区别是Retention.CLASS注释类获得RuntimeInvisible类属性,而Retention.RUNTIME注释获得RuntimeVisible类属性。 This can be observed with javap .这可以通过javap观察到。

Examples on GitHub for you to play with. GitHub 上的示例供您使用。

Annotations with Retention Policy CLASS and RUNTIME are accessible from class byte code. 具有保留策略的注释CLASSRUNTIME可从类字节代码访问。 We need to use a byte code manipulation library(eg ASM) to access the Annotations available in byte code. 我们需要使用字节代码操作库(例如ASM)来访问字节代码中可用的Annotations。

Simple example here 这里的简单例子

By default, annotations are not accessible through Reflection APIs.默认情况下,无法通过反射 API 访问注释。 (RetentionPolicy.CLASS is the default retention policy) (RetentionPolicy.CLASS 是默认的保留策略)

You can specify for your custom annotation if it should be available at runtime, for inspection via reflection.您可以指定您的自定义注释是否在运行时可用,以便通过反射进行检查。 You do so by annotating your annotation definition with the @Retention annotation.您可以通过使用 @Retention 批注对批注定义进行批注来实现。

Try this simple example试试这个简单的例子

@Retention(RetentionPolicy.RUNTIME)
public @interface Version {
    int test();
}

@Version(test= 1)
public class Engineer{
   //code
}

public class Main {
        
    public static void main(String[] args) {
        Engineer engineer = new Engineer();
    
        Annotation[] annotations = engineer.getClass().getAnnotations();
        System.out.printf("%d annotations found.", annotations.length);
    }
}

Try to run the code again by changing the RetentionPolicy of the Version annotation to RetentionPolicy.CLASS and check the difference.通过将版本注释的RetentionPolicy更改为RetentionPolicy.CLASS并检查差异,尝试再次运行代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM