为什么 javac -source 1.5 允许在接口方法上使用@Override?

Why is javac -source 1.5 allowing @Override on interface methods?

这里有一些示例代码 java 如果我理解正确的话,这些代码在 1.5 下是非法的 (自 @Override could not be used for overrides of interface methods until java 1.6):

public class A { 
  public static interface MyInterface { 
    public void myInterfaceMethod();
  }
  public static class MyClass implements MyInterface { 
    @Override public void myInterfaceMethod() {}
  }
} 

我想在我的源代码中找到所有此类 1.5 不兼容的地方, 所以我在我的 ubuntu linux 机器上安装了一个支持 java1.5 的编译器:

sudo apt install openjdk-8-jdk
JAVAROOT=/usr/lib/jvm/java-1.8.0-openjdk-amd64
${JAVAROOT}/bin/javac -version
# javac 1.8.0_232

并编译了上面的java源代码:

${JAVAROOT}/bin/javac -source 1.5 -Xlint:all -Xlint:-options A.java

我预计上面的 java 代码会被拒绝。但它 显然编译成功,尽管在1.5下是非法的。

这是怎么回事?我是否误解了关于 @Override 的 1.5 规则? 还是我误解了 -source 1.5 应该做什么?

FWIW,我注意到 -source 1.4 确实给出了预期的错误:

${JAVAROOT}/bin/javac -source 1.4 -Xlint:all -Xlint:-options A.java
A.java:6: error: annotations are not supported in -source 1.4
      @Override public void myInterfaceMethod() {}
       ^ 
  (use -source 5 or higher to enable annotations)
1 error

看着 Oracle's documentation of javac for Java SE8 它说:

...

-source release

Specifies the version of source code accepted. The following values for release are allowed:

...

  • 1.5

    The compiler accepts code containing generics and other language features introduced in Java SE 5.

  • 5

    Synonym for 1.5.

  • 1.6

    No language changes were introduced in Java SE 6. However, encoding errors in source files are now reported as errors instead of warnings as in earlier releases of Java Platform, Standard Edition.

...

请注意该网站说“Java SE 6 中没有引入任何语言更改”。因此,@Override 可用于断言 interface-methods 被覆盖这一事实似乎不被视为语言变化;相反,它以前不允许的事实可能被视为某些 Java 5 SDK 编译器中的一个错误。

此行为已纠正,因为 @Override 可以在编译后省略并且 JDK 8 编译器理解(并验证)注释。因此,注释对创建的字节码没有任何影响。

使用 -source 1.4,我们得到一个编译错误,因为 Annotations were introduced with Java 1.5,因此包括在运行时保留的注释可能会改变程序的行为,编译器不能忽略它们。


如果我们想找到所有与 Java SE 5 不兼容的地方,我建议下载 Java SE5 JDK from the Oracle Archive(尽管您必须创建一个 Oracle 帐户才能这样做)并尝试用它编译项目JDK.