Gar*_*son 3 java annotations runtime maven
我想@FunctionalInterface在我的代码中使用Java 8,但我希望能够使用Java 6生成的类文件.我认为我应该将源代码版本1.8和目标版本改为1.6.
我将@FunctionalInterface仅用于文档,但我注意到它有@Retention(RetentionPolicy.RUNTIME).如果没有人使用该注释,它会导致问题吗?
如果有人在运行时迭代我的对象的注释,它是否会导致缺少类异常?但是,如果这是真的,那么Google Guava如何声明JSR 305注释依赖关系以提供Maven <scope>,这意味着注释如javax.annotation.Nonnull在运行时也会在Guava中丢失,而不会导致问题?
让我用另一种方式问:如果我在项目中使用Google Guava但不包含JSR 305依赖项,那么如果我对代码使用反射,我是否真的会冒一些错误?如果是这样,会发生什么错误?如果不会发生错误,那么类似地,我可以使用@FunctionalInterfaceJava版本编译的源代码中的注释,1.8但是1.6没有任何运行时错误的风险,甚至使用反射?
我认为那时我应该[设置]源版本
1.8和目标版本1.6.
其实,这是不是可以通过编译新的源代码版本的Java源文件为老版本的JVM版本的目标.Oracles和OpenJDK javac将拒绝-source版本高于版本的编译尝试-target.(但是,我找不到拒绝它的规范,即使手册没有提到它).javac交叉编译功能的唯一想法是,即使您使用较新的JDK进行编译,您仍可以为旧的1.6 JVM编译旧的1.6 Java文件.
您描述的问题是这样的原因.由于Java使用了一种延迟依赖性加载,因此编译器无法保证在运行时对所有依赖项都有适当的类.这也适用于标准库.
但是,有(非官方)工具可以将较新的源惯用法或字节代码编译为较旧的字节代码版本.但这不适用于标准库.如果你想使用更新的课程,你必须自己提供.为此,标准库的特定部分存在一些后端口.
特别是关于您的注释问题:
如果JVM遇到无法检索类文件的带注释的构造(我搜索了Java虚拟机规范SE 8),我无法找到任何应该/可能发生的可靠规范.但是,我在Java语言规范SE 8中找到了一些相关的参考:
注释是将信息与程序构造相关联的标记,但在运行时没有影响.
来自JLS 9.7
此语句反而表明注释(是否存在)不应对JVM的执行产生影响.因此,NoClassDefFoundError由于缺少注释而导致的异常(例如)与此相反.
最后,虽然这个问题的答案,我发现了更具体的陈述:
二进制形式中存在的注释可能在运行时通过Java SE平台的反射库提供,也可能不提供.
和
添加或删除注释对Java编程语言中程序的二进制表示的正确链接没有影响.
这非常清楚地表明,缺少注释不会导致错误,但如果通过反射检查则会被忽略.如果你提供一个类注释与Java 1.8标准库注解,这将是(在某种程度上)上例如,Java 1.6 JVM执行如该注释是不存在,那么这个规格否认产生任何错误.
我写的以下测试也支持这一点:( 注意反射的用法)
@TestAnno
public class Test {
public static void main(String[] args) {
Annotation[] annos = Test.class.getAnnotations();
for (Annotation a : annos) {
System.out.println(a);
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnno {
}
Run Code Online (Sandbox Code Playgroud)
如果编译,它会产生a Test.class和a TestAnno.class.执行时程序输出:
@TestAnno()
Run Code Online (Sandbox Code Playgroud)
因为这是应用的一个注释Test.现在,如果TestAnno.class在没有任何修改,删除Test.class(这是指TestAnno与LTestAnno;在字节码序列),并Test再次执行,它只是做任何输出.所以我的JVM确实忽略了缺少的注释,并且没有生成任何错误或异常(在Linux上使用OpenJDK版本1.8.0_131进行了测试).
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |