maven-compiler-plugin 源不能按预期工作

maven-compiler-plugin source not work as expect

我的本地有 java11,我正在使用 maven-compiler-plugin 将它的 source/target 设置为 1.8,在我的代码中我使用的是 Objects.requireNonNullElse(null, new Object());,这是不支持的在 java 8. 当我 运行 mvn package 它可以正常工作。我知道 maven-compiler-plugin 中的 source 参数指定了你想使用哪个 java 版本来编译你的源代码,我将它设置为 1.8,但是 mvn package 仍然可以成功编译源代码,即使我使用了一些方法java 不支持 8. 怎么会这样?谢谢

你可以在这里找到我的本地设置

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
$ java -version
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment 18.9 (build 11.0.12+7)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.12+7, mixed mode)

语言级别(例如 lambda 的存在或 non-existence)和标准库之间存在差异。你的问题是后者。

Maven(委托给 javac),将始终使用任何 JDK 你用来编译的标准库,因为它怎么可能使用其他任何东西?

假设您正在尝试以 Java 8 为目标,但您正在使用 JDK 17 进行编译。假设您使用了 Java 8 中存在的 class但在 Java 9 中被删除了。 Java 17 应该如何优雅地处理这个问题?它没有 class,因为它已被删除。它怎么能对不存在的东西做 type-checking 呢?不能。

您的情况恰恰相反:您所依赖的 class 是在更新的 Java 版本中引入的,而不是您的目标,但从根本上讲,问题是相同的。

Java 确实没有办法跟踪在什么阶段引入了哪些 classes 和方法,除了无法表达全部可能更改的注释(例如删除案例 I已经提到过——你不能给不存在的东西添加注释)。为了能够正确支持您期望的那种行为,JDK 需要了解所有以前版本的所有 classes 的所有方法的所有签名,并且它没有那。

如果这对您来说是个问题,我明白为什么会这样,那么您应该使用与您实际目标版本相匹配的 JDK 版本进行编译。

您可能还可以使用其他插件,但如果有的话我就不知道了。 IntelliJ 的检查发现 API 不兼容,这至少证明以编程方式检测此问题在技术上是可行的。