代码之家  ›  专栏  ›  技术社区  ›  Garret Wilson

Java运行时保留注释在早期Java版本中的兼容性

  •  3
  • Garret Wilson  · 技术社区  · 7 年前

    我想使用 @FunctionalInterface 在我的代码中使用Java 8,但我希望能够将生成的类文件与Java 6一起使用 1.8 1.6 .

    我会使用 只是为了文档,但我注意到它有 @Retention(RetentionPolicy.RUNTIME) 。如果没有人使用该注释,它会引起问题吗?

    如果有人在运行时迭代我的对象的注释,是否会导致缺少类异常?但如果这是真的,谷歌番石榴怎么能做到呢 declare the JSR 305 annotation dependency 拥有一个专家 <scope> 的,这意味着注释,例如 javax.annotation.Nonnull

    @功能接口 用Java版本编译的源代码中的注释 1.8 1.6 即使使用反射,也不会有运行时错误的风险?

    2 回复  |  直到 7 年前
        1
  •  9
  •   Community Fabien Hure    4 年前

    1.8 ,目标版本为 1.6 .

    事实上是的 可以为较旧的JVM目标版本编译较新源版本的Java源文件。Oracles和OpenJDK javac -source 版本高于 -target manual 没有提及)。唯一的想法 爪哇语

    然而,有一些(非官方)工具可以将较新的源习惯用法或字节码编译成较旧的字节码版本。但这并不适用于标准库。如果你想使用更新的类,你必须自己提供它们。为此,标准库的特定部分有一些后端端口。

    特别是关于您的注释问题:

    我无法找到任何可靠的规范,说明如果JVM遇到无法检索类文件的带注释构造,应该/可能会发生什么情况(我搜索了 Java virtual machine specification SE 8 ). 然而,我在 Java language specification SE 8

    注释是一种标记,它将信息与程序构造相关联,但在运行时不起作用。

    从…起 JLS 9.7

    这句话表明注释(存在或不存在)不应该对JVM的执行产生影响。因此,例外情况(例如 NoClassDefFoundError

    最后,尽管 this question

    二进制形式的注释可能在运行时通过Java SE平台的反射库可用,也可能不可用。

    从…起 JLS 9.6.4.2

    添加或删除注释不会影响Java编程语言中程序二进制表示的正确链接。

    从…起 JLS 13.5.7

    这相当清楚地表明,丢失的注释将 不会导致错误 如果你上课 有了Java 1.8标准库注释,它将(以某种方式)在Java 1.6 JVM上执行,而在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 {
    }
    

    如果编译,它将生成一个 Test.class 和a TestAnno.class

    @TestAnno()
    

    因为这是应用于 Test .现在,如果 TestAnno.class类 在没有任何修改的情况下删除 Test.class测试类 TestAnno LTestAnno; 字节码中的序列)和 再执行一次,就是这样 不输出任何内容 .所以我的JVM确实是 忽略 生成任何错误或异常(使用OpenJDK版本测试 1.8.0_131

        2
  •  0
  •   Kayaman    7 年前

    与任何类加载情况一样,如果不需要(或者更确切地说,不需要加载)该类,则该类在运行时是否不存在无关紧要。运行时注释通常有相同的问题,因为如果在运行时保留它们,通常意味着有基于它们的逻辑,这意味着它们的类也被加载。

    @FunctionalInterface 没有运行时逻辑,所以。。。 Why does @FunctionalInterface have a RUNTIME retention? @Documented 注释。