2016-12-05 125 views
3

在我的項目,我們將使用Java 7 maven-compiler-plugin,我們假設Maven的編譯後,所有這一切是用Java 8中的代碼不應該編譯成功。Maven的編譯器插件和Java 7配置,但仍編譯的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("/"))); 

而我想的是,既然我配置Java版本是7的Maven並且在編譯之後,使用Java 8的文件不應該成功編譯並顯示錯誤,例如「...僅在源級1.8或更高版本中允許」。

回答

7

編譯器插件,其直接映射到Java編譯器javac(當它是所使用的一個)的-source and -target選項的<source><target>標誌,是generally misunderstood

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

在這裏的例子,你必須在javac編譯JDK 8的指示對於檢查源代碼的Java 7,而實際上的情況下,該行

buffer.append(Arrays.stream(arg).collect(Collectors.joining("/"))); 

不使用任何Java 8個具體的源代碼。當然,它使用Java 8特定,但源代碼本身將由JDK 7的編譯器完全可以理解的。

  • 沒有lambda表達式。在您的管道添加一個簡單map(i -> i),然後javac就會報錯,告訴你:

    lambda expressions are not supported in -source 1.7

    它檢測到源代碼中使用的特定功能不在集合的JDK 7的源代碼可用的功能。

  • 接口上沒有靜態方法的調用。用Stream.of(arg)而不是Arrays.stream(arg)替換您的流管道。這個時候,你會得到一個錯誤:

    static interface method invocations are not supported in -source 1.7

    Arrays不是接口,所以調用靜態方法stream對類是完全合法的JDK 7的源代碼。但是,Stream是一個接口(當然,您正在使用的是JDK 8編譯器已知的接口),並且在Java 8之前,接口不能包含靜態方法。因此,它不是有效的Java 7源代碼。

還有更多類似的,但關鍵是不要在這裏介紹他們全部(type annotationsrepeated annotationsmethod referencesintersection types in cast ...你可以看到他們的in javac source code for example)。總而言之,javac沒有理由因該源代碼和-source 7選項而失敗。

target完全是另一個野獸;這在這裏不是問題,因此足以說明它指示javac生成以VM的指定版本爲目標的字節碼。它並不能確保生成的字節代碼實際上可以與所述版本的VM一起運行。如果您想確保使用-bootclasspath選項。


回到手頭的任務,這實際上是編譯失敗。與Maven,you have 2 solutions

  • Fork編譯器,以及指向executable設置爲JDK 7編譯器。
  • 或者(首選),使用toolchains的機制來確保每個Maven插件(瞭解工具鏈)在整個構建過程中都使用此JDK(例如,使用JDK安裝的javadoc工具的Javadoc插件)。
+0

非常感謝!我對此有了更多的瞭解!真的很棒的解釋! – TryMyBest

+0

你的回答是正確和詳細的。謝謝! – sudoz

0

我同意@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>