简体   繁体   English

递归使用@Retention注释,怎么可能?

[英]Recursive usage of @Retention annotation , how is it possible?

In the source code of @Retention annotation in java, @Retention is used in its definition itself, hows that possible. 在java中的@Retention注释的源代码中, @ Rettention在其定义中使用,如此可能。

Even the RetentionPolicy is set at RUNTIME , so how could it get executed before its not ready to run. 即使RetentionPolicy设置为RUNTIME ,那么如何在它未准备好运行之前执行它。

package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

This is not really recursive . 这不是真正的递归 It is nothing but a forward reference to a class respectively interface which is following "later" on. 它只不过是对“后来”后面的类分别接口的前向引用。 And Java allows using forward references in general. Java允许使用前向引用。 There are various restrictions to that (see the Java Language Specification, for example section 8.3.2.2 ) - but none of these restrictions would apply here. 对此有各种限制(请参阅Java语言规范,例如第8.3.2.2节) - 但这些限制都不适用于此。

Beyond that: keep in mind there is no special compilation step here. 除此之外:请记住,这里没有特殊的编译步骤。 The compiler simply creates a ordinary class file for the Retention interface. 编译器只是为Retention接口创建一个普通的类文件。 But then: the compiler most likely has hardcoded knowledge about this interface. 但那时:编译器很可能拥有关于此接口的硬编码知识。 In case RetentionPolicy.SOURCE is used, the compiler will exclude the annotation even from the compiled class file. 如果使用RetentionPolicy.SOURCE ,编译器将从编译的类文件中排除注释。 This means that the compiler must be doing some sort of checking (to figure if something is annotated and has SOURCE policy enabled). 这意味着编译器必须进行某种检查(以确定是否注释了某些内容并启用了SOURCE策略)。

In other words: the compiler might contain something like 换句话说:编译器可能包含类似的内容

if (x instaceof Retention) ...

and this code exists within the compiler. 并且此代码存在于编译器中。 The above works fine when compiling some other annotation, but it also works when the Retention interface itself is compiled. 编译其他注释时,上述工作正常,但在编译Retention接口本身时也可以正常工作。

But the key message is: there is no recursion, just a forward reference. 但关键信息是:没有递归,只是一个前向引用。 Something gets used that is defined later on. 稍后定义使用的东西。

It doesn't need a Retention class. 它不需要Retention类。 Source code first convert to AST. 源代码首先转换为AST。 It just need the Retention 's qualifield name to get the annotation value. 它只需要Retention的qualifield名称来获取注释值。 Here is code from OpenJDK 这是OpenJDK的代码

Define the Retention by class name: 按类名定义Retention

// com.sun.tools.javac.code.Symtab
protected Symtab(Context context) throws CompletionFailure {
    ...
    retentionType = enterClass("java.lang.annotation.Retention");
    ...
}

Use the com.sun.tools.javac.code.Type retentionType to get the RetentionPolicy from AST (line 4 syms.retentionType.tsym ): 使用com.sun.tools.javac.code.Type retentionType从AST获取RetentionPolicy (第4行syms.retentionType.tsym ):

// com.sun.tools.javac.code.Types
public RetentionPolicy getRetention(Attribute.Compound a) {
    RetentionPolicy vis = RetentionPolicy.CLASS; // the default
    Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym);
    if (c != null) {
        Attribute value = c.member(names.value);
        if (value != null && value instanceof Attribute.Enum) {
            Name levelName = ((Attribute.Enum)value).value.name;
            if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
            else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
            else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
            else ;// /* fail soft */ throw new AssertionError(levelName);
        }
    }
    return vis;
}

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

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