考虑以下代码:
A.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@interface A{}
C.java:
import java.util.*;
@A public class C {
public static void main(String[] args){
System.out.println(Arrays.toString(C.class.getAnnotations()));
}
}
编译和运行工作符合预期:
$ javac *.java
$ java -cp . C
[@A()]
但请考虑以下内容:
$ rm A.class
$ java -cp . C
[]
我本以为它会抛出一个ClassNotFoundException
,因为缺少@A
。但是,它会默默地删除注释。
这种行为是否记录在JLS中的某个地方,或者它是Sun的JVM的怪癖?这样做的理由是什么?
对于像javax.annotation.Nonnull
这样的东西,它似乎很方便(它看起来无论如何都应该是@Retention(CLASS)
),但对于许多其他注释,它似乎会在运行时导致各种不好的事情发生。
发布于 2010-08-26 00:19:33
在JSR-175的早期公开草案(注释)中,讨论了编译器和运行时是否应该忽略未知注释,以便在注释的使用和声明之间提供更松散的耦合。一个特定的示例是在EJB上使用特定于应用程序服务器的注释来控制部署配置。如果相同的bean应该部署在不同的应用程序服务器上,如果运行时简单地忽略未知注释而不是引发NoClassDefFoundError,将会很方便。
即使用词有点含糊,我假设您看到的行为是在JLS 13.5.7中指定的:“……删除注释不会影响Java编程语言中程序的二进制表示的正确链接。”我的解释是,如果注释被移除(在运行时不可用),程序仍然应该链接和运行,这意味着当通过反射访问时,未知的注释只是被忽略。
SunJDK5的第一个版本没有正确地实现这一点,但在1.5.0_06中得到了修复。您可以在bug数据库中找到相关的bug 6322301,但是它并没有指向任何规范,只是声称“根据JSR-175规范的领导,未知的注释必须被getAnnotations忽略”。
发布于 2010-08-26 01:10:36
如果你实际有读取@A的代码,并对它做了一些事情,那么代码依赖于类A,并且它将抛出ClassNotFoundException。
如果不是,也就是说没有代码特别关心@A,那么可以说@A并不重要。
https://stackoverflow.com/questions/3567413
复制相似问题