我有一些关于在java中使用注释的问题。
如果注释无法转换为字节码,那么这些信息会在哪里发生? 元数据在哪里? Java Reflection如何使用这些信息?
编译器如何处理注释?
当我们说,
@Override
public void doSomething(){
}
java编译器用它做什么?
我知道它会检查方法签名,以便该方法应该是一个完全重写的方法,但是如何?
答案 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.CLASS
,RetentionPolicy.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()和朋友进行访问。