@Retention注释的递归使用,它怎么可能?
在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();
}
这不是真正的递归。 它不过是对“稍后”之后的类和接口的前向引用。 一般而言,Java允许使用前向引用。 对此有各种限制(请参阅Java语言规范,例如第8.3.2.2节) - 但这些限制都不适用于此。
除此之外:请记住,这里没有特别的汇编步骤。 编译器只是为保留接口创建一个普通的类文件。 但是,然后:编译器很可能具有关于此接口的硬编码知识。 如果使用RetentionPolicy.SOURCE,则编译器将从编译的类文件中排除注释。 这意味着编译器必须进行某种检查(以确定是否注释了某些内容并启用了SOURCE策略)。
换句话说:编译器可能包含类似的东西
if (x instaceof Retention) ...
并且此代码存在于编译器中。 上面的代码在编译其他注释时很好,但是它也可以在编译保留接口本身时使用。
但关键的信息是:没有递归,只是一个前向引用。 之后定义的东西被使用了。
它不需要Retention
类。 源代码首先转换为AST。 它只需要Retention
的qualifield名称来获取注释值。 这里是来自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(第4行syms.retentionType.tsym
)获取RetentionPolicy
:
// 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;
}
链接地址: http://www.djcxy.com/p/40879.html
上一篇: Recursive usage of @Retention annotation , how is it possible?
下一篇: Running a Perl script from crontab when you use Perlbrew