2016-12-05 6 views
3

私のプロジェクトでは、Java 7をmaven-compiler-pluginに使用する予定であり、Mavenコンパイル後にJava 8を使用しているコードはすべてコンパイルできません。Java 7で構成されていてもJava 8コードをコンパイルしているMavenコンパイラプラグイン

私の場合は、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のバージョンを設定するので、Mavenの中に7をするということですコンパイルした後、Java 8を使用するファイルは正常にコンパイルされず、 "...はソースレベル1.8以上でのみ許可されます"などのエラーが表示されます。

答えて

7

Javaコンパイラjavac(それが使用されているものである)の-source and -targetオプションに直接マップコンパイラプラグインの<source><target>フラグは、generally misunderstoodです。

sourcejavacは、指定されたJDKバージョンのJavaソースファイルをコンパイルするように指示しません。 javacは、受け入れられたソースコードのバージョンを確認するよう指示します。これは非常に異なります。メジャーバージョンのJavaでは、ソースコードの構文が変更されることがあります。たとえば、Java 1.4では、List<String>のようなジェネリックを含むソースコードを書くことはできませんでした。それは有効ではありませんでした。しかし、Java 5ではこれが可能です。つまり、新しい種類のJavaソースコードがJDK 5コンパイラによって受け入れられました。 List<String>に直面しているJDK 1.4コンパイラは、JDK 5コンパイラが完全にそれを受け入れると、そのことを知らないのでエラーになるだけです。オプションを設定すると、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コンパイラによって完全に理解できます。

  • ラムダ式はありません。あなたのパイプラインでの簡単なmap(i -> i)を追加し、javacエラーになります、あなたを伝える:

    lambda expressions are not supported in -source 1.7

    それは、ソースコードはJDK 7のソースコードの機能のセットでは使用できない特定の機能を使用したことを検出しました。

  • インターフェイスに静的メソッドが呼び出されることはありません。 Arrays.stream(arg)ではなく、ストリームパイプラインをStream.of(arg)に置き換えてください。この時間は、あなたがエラーを取得します:

    static interface method invocations are not supported in -source 1.7

    Arraysがインタフェースではありませんので、そのクラスの静的メソッドstreamを呼び出すことは完全に有効なJDK 7のソースコードです。ただし、Streamはインターフェイスです(もちろん、使用しているJDK 8コンパイラには知られています)。また、Java 8より前では、インターフェイスに静的メソッドが含まれていない可能性があります。したがって、有効なJava 7ソースコードではありません。

あり、よりそのようなものですが、ポイントはここに(あなたがそれらin javac source code for exampleのすべてを見ることができますtype annotationsrepeated annotationsmethod referencesintersection types in cast ...)それらすべてを説明することではありません。まったく、javacがそのソースコードと-source 7オプションで失敗する理由はありません。

targetは完全に別の獣です。これは問題ではないので、javacにVMの指定されたバージョンを対象とするバイトコードを生成するように指示するだけで十分です。実際には、生成されたバイトコードが実際にはそのバージョンのVMで実行されることは保証されません。そのようにしたい場合は、-bootclasspathオプションを使用してください。


実際にここでの作業に戻ります。ここで実際にコンパイルが失敗します。 Mavenの、you have 2 solutions付:

  • Forkコンパイラ、およびJDK 7コンパイラにexecutableポインティングを設定します。
  • (すべてのMavenプラグイン(ツールチェーンを認識している)がこのJDKをビルド全体で使用していることを確認するには、toolchainsのメカニズムを使用してください(例:JDKインストールのjavadocツールを使用するJavadocプラグイン)。
+0

ありがとうございます!私はそれについてもっと理解しています!本当にすごい説明! – TryMyBest

+0

あなたの答えは正確で詳細です。ありがとう! – sudoz

0

@Tunakiが述べていることすべてに同意します。オプション1を使うことに決めたら、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>