使用Java 7配置的Maven编译器插件,但仍编译Java 8代码

时间:2016-12-05 19:40:50

标签: java eclipse maven maven-compiler-plugin

在我的项目中,我们将使用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或以上“。

2 个答案:

答案 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 misunderstoodtype annotationsrepeated annotationsmethod references ...你可以看到所有这些intersection types in cast)。总而言之,javac没有理由使用该源代码和-source 7选项失败。

target完全是另一个野兽;这不是问题所在,因此可以说它指示javac生成以VM的指定版本为目标的字节代码。它不能以任何方式确保生成的字节代码实际上将与所述VM版本一起运行。如果您想确保这一点,则使用-bootclasspath选项。

回到这里的任务,这实际上是为了使编译在这里失败。使用Maven,in javac source code for example

  • you have 2 solutions编译器,并设置指向JDK 7编译器的Fork
  • 或(首选),使用executable的机制,以确保每个Maven插件(知道工具链)在整个构建过程中使用此JDK(例如,使用{{1}的Javadoc插件JDK安装工具)。

答案 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>