编译器如何处理注释?

时间:2011-03-25 12:47:48

标签: java annotations

我有一些关于在java中使用注释的问题。

如果注释无法转换为字节码,那么这些信息会在哪里发生? 元数据在哪里? Java Reflection如何使用这些信息?

编译器如何处理注释?

当我们说,

@Override
public void doSomething(){
}

java编译器用它做什么?

我知道它会检查方法签名,以便该方法应该是一个完全重写的方法,但是如何?

6 个答案:

答案 0 :(得分:10)

有三种类型的注释,请参阅http://download.oracle.com/javase/6/docs/api/java/lang/annotation/RetentionPolicy.html

@Override是一种特殊情况,因为编译器会进行额外的检查。

答案 1 :(得分:4)

@Override是一个类型注释 - 用于检查特定方法是否遵循重写方法的约定 - 因此它在运行时不可用(因此逻辑上没有' t存在于编译的字节码中。

  

我知道它会检查方法签名,以便该方法应该是一个完全重写的方法,但是如何

在读取源文件并将其转换为字节码的过程中,例如,根本不使用反射。有关其他编译器信息,请参阅The Java Programming Language Compiler - javac

答案 2 :(得分:3)

注释,例如@Override实现为public @interface @Override {}的{​​{3}},可以允许注释存储在类文件中RetentionPolicy.CLASSRetentionPolicy.RUNTIME )或被丢弃(RetentionPolicy.SOURCE)。

@Override方法的RetentionPolicy为RetentionPolicy.SOURCE,目标为ElementType.METHOD(意味着此方法只能在方法声明中注释)。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

PS 如果您想要反思地阅读注释,则必须将RetentionPolicy设置为RetentionPolicy.RUNTIME

答案 3 :(得分:2)

首先,有两种注释:运行时可访问(2种)而不是运行时可访问。注释的行为由保留策略通过注释声明的注释完成:-)。例如:

@Retention(RetentionPolicy.RUNTIME) // effectively visible to JVM Runtime
public @interface MethodInfo {
    String author() default "unspecified";
    String lastModification() default "unspecified"; // Format: yyyy-mm-dd
    ImplementationStatus implementationStatus();
}

JVM运行时可见注释可以在带注释的代码执行期间(或由JVM加载时)通过反射进行访问。您将这些注释用作元数据持有者。元数据可以由其他代码处理以执行各种事情,例如。在执行给定方法之前检查带注释的方法实现状态。

但有人必须编写代码才能通过反射使用注释matedata!最好的示例是应用程序服务器(AS),它根据需要从JAR文件中加载类,这些文件位于某个特定目录中。 AS可以包含检查每个已加载类的代码,以查找由@Initialization批注注释的静态方法,并立即执行这些方法。此注释类型由AS定义,为AS创建JAR和类的人在开发期间使用它。

在编译期间使用并计算运行时期间不可用的注释。 @Override是很好的例子。编译器插件可以使用自定义源仅注释,或者如果代码由其他代码按需编译。

答案 4 :(得分:0)

这个很简单。编译器只检查超类中具有相同名称和相同数量的参数,它们的顺序和类型的方法。如果方法具有@Override注释,并且未找到此类方法,则会生成错误。

更有趣的问题是编译器如何处理在运行时具有意义的注释。我假设它们是在字节码中添加的,但是在一些带有元信息的特殊部分中。因此,在运行时jvm可以访问meta部分。作为证明,您始终可以在任何getAnnotations()对象上调用class

答案 5 :(得分:-2)

编译注释(最终是常量数据)存在于类文件中,可以使用适当的方法getAnnotations()和朋友进行访问。