在我的项目中,我们将使用Java 7作为maven-compiler-plugin
,并且我们假设在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或以上“。
答案 0 :(得分:8)
编译器插件的<source>
和<target>
标志,它直接映射到Java编译器javac
的{{3}}选项(当它是使用的那个时),是-source
and -target
。
source
不指示javac
使用指定的JDK版本编译Java源文件。它指示javac
检查接受的源代码的版本,这是非常不同的。 Java的主要版本有时会改变源代码的语法。例如,在Java 1.4中,您无法编写包含泛型的源代码,例如List<String>
;它不是有效的。但是使用Java 5,您可以,这意味着JDK 5编译器现在接受了一种新的Java源代码。面向List<String>
的JDK 1.4编译器只能出错,因为当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("/")));
不使用任何Java 8特定的源代码。当然,它使用Java 8特定的类,但是JDK 7编译器完全可以理解源代码本身。
没有lambda表达式。在您的管道中添加一个简单的map(i -> i)
,然后javac
会出错,告诉您:
不支持
-source 1.7
lambda表达式
它检测到源代码使用了JDK 7源代码功能集中不可用的特定功能。
接口上没有静态方法的调用。将您的Stream管道替换为Stream.of(arg)
而不是Arrays.stream(arg)
。这一次,您将收到错误:
不支持
-source 1.7
静态接口方法调用
Arrays
不是接口,因此在该类上调用静态方法stream
是完全有效的JDK 7源代码。但是,Stream
是一个接口(当然,您正在使用的JDK 8编译器已知),并且在Java 8之前,接口不能包含静态方法。因此,它不是有效的Java 7源代码。
还有更多相似内容,但重点不是在这里描述所有内容(generally misunderstood,type annotations,repeated annotations,method references ...你可以看到所有这些intersection types in cast)。总而言之,javac
没有理由使用该源代码和-source 7
选项失败。
target
完全是另一个野兽;这不是问题所在,因此可以说它指示javac
生成以VM的指定版本为目标的字节代码。它不能以任何方式确保生成的字节代码实际上将与所述VM版本一起运行。如果您想确保这一点,则使用-bootclasspath
选项。
回到这里的任务,这实际上是为了使编译在这里失败。使用Maven,in javac
source code for example:
答案 1 :(得分:0)
我同意@Tunaki所说的一切。以下是maven文档中的配置示例,如果您决定使用选项1,可以帮助您。
<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>