@Retention注解的递归使用,这是否可能?

7
在Java中@Retention注解的源代码中,@Retention在其自身定义中使用,这是怎么可能的。
即使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();
}
2个回答

2
这并不是真正的递归。它只是一个对随后“稍后”跟随的类或接口的前向引用。Java通常允许使用前向引用。虽然有各种限制(例如请参见Java语言规范中的8.3.2.2部分),但这些限制都不适用于此处。
除此之外,请记住,这里没有特殊的编译步骤。编译器只为Retention接口创建一个普通的类文件。但是:编译器很可能对此接口有硬编码的了解。如果使用RetentionPolicy.SOURCE,则编译器将从编译后的类文件中排除注释。这意味着编译器必须进行某种检查(以确定某些内容是否被注释并启用了SOURCE策略)。
换句话说:编译器可能包含以下内容:
if (x instaceof Retention) ...

这段代码存在于编译器中。当编译一些其他的注释时,上述代码可以正常工作,但是当保留接口本身被编译时,它也可以正常工作。
但是关键信息是:这里没有递归,只有向前引用。某些后面定义的内容被使用了。

这同样适用于@Target,它具有@Target(value=ANNOTATION_TYPE)。+1。我感到害怕并在谷歌上搜索了这个问题,最终来到了这里。 - user2453382
1
@MohammadRakibAmin 非常欢迎您的回复。总是很高兴听到对旧内容的反馈;-) - GhostCat

1
它不需要一个名为Retention的类。源代码首先转换成AST。它只需要Retention的限定名称来获取注释值。以下是来自OpenJDK的代码。
通过类名定义Retention:
// com.sun.tools.javac.code.Symtab
protected Symtab(Context context) throws CompletionFailure {
    ...
    retentionType = enterClass("java.lang.annotation.Retention");
    ...
}

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接