2017-02-13 16 views
12

http://www.concretepage.com/java/jdk-8/java-8-unaryoperator-binaryoperator-exampleの例を使って遊んでいました。Java 8ストリームの静的コンテキストから非静的メソッドを参照することはできません

非静的メソッドは、から参照することはできません。

私が本当に混乱見つけることコレクターを形成するとき、私は誤ってジェネリックの一つに間違ったタイプを入れたときに、Javaコンパイラは私に非常に誤解を招くようなメッセージを与えることです

Map<String, Map<Integer, Integer>> mapOfStudents = list.stream().collect(Collectors.groupingBy(Student::getClassName, 
      Collectors.toMap(Student::getName, Student::getAge))); 

マイメートル:静的コンテキスト

私のエラーは、実際にインスタンスコンテキスト対静的とは何の関係もありませんistakeは汎用戻り型です。私はそれを修正して置く:

Map<String, Map<String, Integer>> mapOfStudents 

すべてが正常に戻ります。

誰かがこのような混乱しやすいエラーメッセージの原因を説明することはできますか?私はそれが良いものだと確信していますが、私はそれを理解することができません。

EDIT:

~$ java -version 
openjdk version "1.8.0_121" 
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-0ubuntu1.16.04.2-b13) 
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode) 
+0

私は 'javac'(はるかに明確になりました)と非常に異なるメッセージを受け取ります。メソッド参照/ lambdasを使用すると、Eclipseでも同様のエラーメッセージが表示されますが、 –

+1

Javaコンパイラの正確なバージョンとバージョンを提供してください。タイプ推論はかなり頻繁に変更されているものの1つです。 – biziclop

+0

詳細については、編集セクションを参照してください。私はIntellij Ideaを実行しています。2016.3 – yuranos87

答えて

18

まずそのメッセージがないJavaコンパイラ(javacの)によって、しかしのIntelliJ IDEAによって発行されていることに留意すべきです。ビルドプロセスを実際に起動すると、「メッセージビルド」ウィンドウでjavacメッセージが表示されます。エディタウィンドウに表示されるのは、IDEA自身によって生成されたメッセージであり、それらは異なる場合があります。

IntelliJ IDEAでのメソッド参照の解決の実装により、エラーメッセージが誤解を招くことがあります。対応するSAM(単一の抽象メソッド)引数の数がメソッド引数の数に1を加えた場合にのみ、非静的メソッド参照が解決されるとみなします。および最初のSAM引数型は、クラスを含むメソッドと互換性があります。 the implementationを参照してください(上記のisSecondSearchPossibleメソッド、varargsメソッドにはいくつかの追加魔法が実行されます)。

プログラムにエラーがなければ正しく動作します。しかし、タイプが一致していない場合はtoMapに渡されたFunctionの汎用引数は代用できないので、Function<T, R>のままで、そのapplyメソッドの最初の引数はStudentに対応しない単純にTです。したがって、いわゆる「第2の検索」は失敗し、IDEAは、この方法が静的コンテキストから参照されると考える。静的コンテキストと非静的コンテキストの両方はここでは適用できませんが、非静的コンテキストは、少なくとも引数の数に応じてメソッドをよりよく一致させます。getName()メソッドは引数を受け取りません。一方、IDEAロジックは、 "非静的コンテキストが適用できない場合は、静的コンテキストです"というエラーメッセージです。

これはバグ、または少なくともユーザビリティの問題と考えられます。私はhereに基づいてsimilar questionに基づいてログしました。うまくいけば私たちはそれを修正します。

免責事項:私はIntelliJ IDEA開発者です。

更新:IDEA 2017.2で修正されました。

+0

'javac'と一致しない場合、バグです。 – EJP

+3

@ EJP、それはプログラムが間違っていることに同意しますが、エラーメッセージが異なります。 Java言語仕様は、正しいプログラムが何であるかを指定しますが、エラーメッセージが間違ったプログラムを探す方法を正確に指定するものではありません。 Eclipseコンパイラのエラーメッセージも異なっており、この場合実際にはjavacメッセージよりも実際のエラーを簡単に見つけ出すことができます。これをEclipseコンパイラのバグと見なしますか? :-) –

+0

私には、 "静的でない静的な参照"は、 "一般的な型は一致しません"という問題とはまったく異なります。 – lwpro2

関連する問題