web-dev-qa-db-ja.com

Java 8ストリームの静的コンテキストから非静的メソッドを参照することはできません

http://www.concretepage.com/Java/jdk-8/Java-8-unaryoperator-binaryoperator-example のサンプルをいじっていました。

本当に紛らわしいのは、コレクターを作成するときに誤ってジェネリックの1つに間違った型を入力すると、Javaコンパイラーが非常に誤解を招くメッセージを与えることです。

非静的メソッドは静的コンテキストから参照できません

私のエラーは、実際には静的コンテキストとインスタンスコンテキストとは関係ありません。

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

私の間違いは一般的な戻り値の型にあります。私がそれを修正して置くとき:

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

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

誰かがそのような紛らわしいエラーメッセージの背後にある理由を説明できますか?私はそれが良いものだと確信していますが、私はそれを把握することに失敗しました。

編集:

~$ 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)
28
yuranos87

メッセージはJavaコンパイラ(javac)ではなく、IntelliJ IDEAによって発行されます。実際にビルドを起動すると、[メッセージビルド]ウィンドウでjavacメッセージを確認できます。プロセス。エディタウィンドウに表示されるのは、IDEA自体によって生成されたメッセージであり、異なる場合があります。

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

プログラムにエラーがない場合は正常に動作します。ただし、型が一致しない場合、Functionに渡されたtoMapの汎用引数は置換できないため、_Function<T, R>_のままで、そのapplyメソッドが先になります引数は、単にTであり、タイプStudentに対応していません。したがって、いわゆる「2番目の検索」は失敗し、IDEAはメソッドが静的コンテキストから参照されていると考えます。静的コンテキストと非静的コンテキストの両方はここでは適用できませんが、非静的コンテキストはメソッドと一致します少なくとも、getName()メソッドは引数を受け取らないため、引数の数に応じて改善されます。一方、IDEA logicは、非静的コンテキストが適用できない場合、それは静的コンテキストです」というエラーメッセージが表示されます。

私はこれをバグ、または少なくともユーザビリティの問題と考えています。私はちょうどそれを記録しました ここ に基づいて 同様の質問 。うまくいけば修正します。

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

更新:IDEA 2017.2。

35
Tagir Valeev