Maven 编译器插件配置 Java 7 但仍然编译 Java 8 代码
Maven compiler plugin configured with Java 7 but still compiles Java 8 code
在我的项目中,我们将对 maven-compiler-plugin
使用 Java 7 并且我们假设在 Maven 编译之后,所有使用 Java 8 的代码都不会编译成功.
但是,在我的例子中,有一个使用 Arrays.stream(T[] array)
的文件可以从 Java 8 开始使用,它仍然可以成功编译。下面是配置 Java 版本的一些 pom.xml
文件。请你看一下,告诉我为什么我的文件仍然可以编译成功,尽管我将它配置为 Java 7?
对于 pom.xml
,我跳过依赖项等,仅列出属性和构建。
<properties>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
对于我使用 Java 8 中的方法的文件,该行是这样的:
buffer.append(Arrays.stream(arg).collect(Collectors.joining("/")));
而我想要的是,由于我在 Maven 中将 Java 版本配置为 7,并且在编译后,使用 Java 8 的文件不应成功编译并显示如下错误“...只允许在源代码级别 1.8 或更高版本”。
<source>
and <target>
flags of the Compiler Plugin, which maps directly to the -source
and -target
options of the Java compiler javac
(when it is the one used), are .
source
不指示 javac
使用指定的 JDK 版本编译 Java 源文件。它指示 javac
检查接受的源代码的版本,这是非常不同的。 Java 的主要版本有时会更改源代码的语法。例如,在 Java 1.4 中,您不能编写包含泛型的源代码,例如 List<String>
;这是无效的。但是使用 Java 5,你可以,这意味着 JDK 5 编译器现在接受了一种新的 Java 源代码。 JDK 1.4 编译器面对 List<String>
时只能出错,因为它不知道 JDK 5 编译器可以完美地接受它。设置 -source 1.4
选项会告诉 JDK 5 编译器将源代码解释为 JDK 1.4 源代码;因此,如果该代码确实包含泛型,它将失败,因为该源代码在该版本中无效。这也意味着,如果源代码不包含任何 Java 5 特定的源代码,它会用 -source 1.4
.
编译得很好
在这里的例子中,JDK 8 的 javac
编译器被指示检查关于 Java 7 的源代码。实际上,行
buffer.append(Arrays.stream(arg).collect(Collectors.joining("/")));
不使用任何 Java8 特定的源代码。当然,它使用 Java 8 特定的 classes,但是源代码本身完全可以被 JDK 7 编译器理解。
没有 lambda 表达式。在你的pipeline中添加一个简单的map(i -> i)
,然后javac
就会报错,告诉你:
lambda expressions are not supported in -source 1.7
它检测到源代码使用了 JDK 7 个源代码功能集中不可用的特定功能。
接口上没有调用静态方法。用 Stream.of(arg)
而不是 Arrays.stream(arg)
替换您的 Stream 管道。这一次,你会得到一个错误:
static interface method invocations are not supported in -source 1.7
Arrays
不是接口,因此在 class 上调用静态方法 stream
是完全有效的 JDK 7 源代码。但是,Stream
是一个接口(当然,您正在使用的 JDK 8 编译器知道它),并且在 Java 8 之前,接口不能包含静态方法.因此,它是无效的 Java 7 源代码。
还有更多类似的,但重点不是在这里描述它们 (type annotations, repeated annotations, method references, intersection types in cast... you can see all of them in javac
source code for example)。总而言之,javac
没有理由因该源代码和 -source 7
选项而失败。
target
完全是另一种野兽;这不是这里的问题,所以只要说它指示 javac
生成针对指定版本 VM 的字节码就足够了。它不能以任何方式确保生成的字节码实际上会 运行 与所述 VM 版本。如果要确保这一点,则使用 -bootclasspath
选项。
言归正传,这里其实就是让编译失败。使用 Maven,:
- Fork the compiler, and set an executable 指向 JDK 7 编译器。
- 或者(首选),使用 toolchains 的机制,以确保每个 Maven 插件(知道工具链)在整个构建过程中使用此 JDK(即 Javadoc例如插件,它使用 JDK 安装的
javadoc
工具。
我同意@Tunaki 所说的一切。这是 maven 文档中的配置示例,如果您决定使用选项一,它可以为您提供帮助。
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable><!-- path-to-javac --></executable>
<compilerVersion>1.7</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
在我的项目中,我们将对 maven-compiler-plugin
使用 Java 7 并且我们假设在 Maven 编译之后,所有使用 Java 8 的代码都不会编译成功.
但是,在我的例子中,有一个使用 Arrays.stream(T[] array)
的文件可以从 Java 8 开始使用,它仍然可以成功编译。下面是配置 Java 版本的一些 pom.xml
文件。请你看一下,告诉我为什么我的文件仍然可以编译成功,尽管我将它配置为 Java 7?
对于 pom.xml
,我跳过依赖项等,仅列出属性和构建。
<properties>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
对于我使用 Java 8 中的方法的文件,该行是这样的:
buffer.append(Arrays.stream(arg).collect(Collectors.joining("/")));
而我想要的是,由于我在 Maven 中将 Java 版本配置为 7,并且在编译后,使用 Java 8 的文件不应成功编译并显示如下错误“...只允许在源代码级别 1.8 或更高版本”。
<source>
and <target>
flags of the Compiler Plugin, which maps directly to the -source
and -target
options of the Java compiler javac
(when it is the one used), are
source
不指示 javac
使用指定的 JDK 版本编译 Java 源文件。它指示 javac
检查接受的源代码的版本,这是非常不同的。 Java 的主要版本有时会更改源代码的语法。例如,在 Java 1.4 中,您不能编写包含泛型的源代码,例如 List<String>
;这是无效的。但是使用 Java 5,你可以,这意味着 JDK 5 编译器现在接受了一种新的 Java 源代码。 JDK 1.4 编译器面对 List<String>
时只能出错,因为它不知道 JDK 5 编译器可以完美地接受它。设置 -source 1.4
选项会告诉 JDK 5 编译器将源代码解释为 JDK 1.4 源代码;因此,如果该代码确实包含泛型,它将失败,因为该源代码在该版本中无效。这也意味着,如果源代码不包含任何 Java 5 特定的源代码,它会用 -source 1.4
.
在这里的例子中,JDK 8 的 javac
编译器被指示检查关于 Java 7 的源代码。实际上,行
buffer.append(Arrays.stream(arg).collect(Collectors.joining("/")));
不使用任何 Java8 特定的源代码。当然,它使用 Java 8 特定的 classes,但是源代码本身完全可以被 JDK 7 编译器理解。
没有 lambda 表达式。在你的pipeline中添加一个简单的
map(i -> i)
,然后javac
就会报错,告诉你:lambda expressions are not supported in
-source 1.7
它检测到源代码使用了 JDK 7 个源代码功能集中不可用的特定功能。
接口上没有调用静态方法。用
Stream.of(arg)
而不是Arrays.stream(arg)
替换您的 Stream 管道。这一次,你会得到一个错误:static interface method invocations are not supported in
-source 1.7
Arrays
不是接口,因此在 class 上调用静态方法stream
是完全有效的 JDK 7 源代码。但是,Stream
是一个接口(当然,您正在使用的 JDK 8 编译器知道它),并且在 Java 8 之前,接口不能包含静态方法.因此,它是无效的 Java 7 源代码。
还有更多类似的,但重点不是在这里描述它们 (type annotations, repeated annotations, method references, intersection types in cast... you can see all of them in javac
source code for example)。总而言之,javac
没有理由因该源代码和 -source 7
选项而失败。
target
完全是另一种野兽;这不是这里的问题,所以只要说它指示 javac
生成针对指定版本 VM 的字节码就足够了。它不能以任何方式确保生成的字节码实际上会 运行 与所述 VM 版本。如果要确保这一点,则使用 -bootclasspath
选项。
言归正传,这里其实就是让编译失败。使用 Maven,
- Fork the compiler, and set an executable 指向 JDK 7 编译器。
- 或者(首选),使用 toolchains 的机制,以确保每个 Maven 插件(知道工具链)在整个构建过程中使用此 JDK(即 Javadoc例如插件,它使用 JDK 安装的
javadoc
工具。
我同意@Tunaki 所说的一切。这是 maven 文档中的配置示例,如果您决定使用选项一,它可以为您提供帮助。
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable><!-- path-to-javac --></executable>
<compilerVersion>1.7</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>