使用 Maven 编译为旧版本的 Java

Man*_*ami 1 java maven

我的代码是用 Java 17 编写的。我想知道是否有办法编译到较旧的 Java 版本(8 及更高版本)。

网上很多人建议我应该使用这样的东西:

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,我遇到以下问题:

Caused by: java.lang.IllegalStateException: warning: source release 17 requires target release 17
Run Code Online (Sandbox Code Playgroud)

使用maven-compiler-pluginrelease也没有帮助。

我不明白的是,如果目标和源需要完全相同,那么为什么我们的事件需要两者?

顺便说一句,我正在使用 Maven 3.8.3。

Pat*_*k W 6

在编译器兼容性方面,您对 JDK 的期望是错误的。编译器不是向前兼容的,而是向后兼容的。因此,在您的情况下,将编译器设置targetJava 1.8Java 17source将不起作用。

Java 17中有一些新功能与Java 1.8不兼容,因此Java JDK 1.8将无法理解它们是什么,并且肯定会抛出语法错误。这解释了您从 Maven 编译器插件收到的警告。

与此同时,Java 17又遥遥领先。虽然它可以理解以前版本的 Java 中存在的所有语法,但您会遇到由于缺少类而导致的编译时错误。此类错误的一个示例是java.lang.NoClassDefFoundErrororjava.lang.ClassNotFoundException因为某些类已被弃用和删除。

从Java 9开始,Java 决定仅支持最多三个版本。因此,如果您使用的是Java 17,那么最后的支持将是Java 14在这种情况下,如果您编写与JDK 14兼容的所有代码并使用JDK 17进行编译,它将继续适用于其间的所有版本。

这与Java 1.8及更低版本的情况类似。该代码必须与您的目标环境兼容。因此,如果您的版本targetCompatibilityJava 1.8,那么您的版本sourceCompatibility也应该是Java 1.8及以下版本。

一个例子:

<!-- Correct -->
<properties>
    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<!-- Wrong -->
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>
</properties>
Run Code Online (Sandbox Code Playgroud)

  • 我在这个草案中发现了支持的源和目标选项的“一+三回”政策(未最终确定)[*JEP 182:退休 javac -source 和 -target 选项的政策*](https://openjdk. java.net/jeps/182)。但我找不到任何官方的政策声明。您可以引用参考文献以供记录吗?(另外,非常好的答案。) (2认同)