Eclipse JDTでメソッド参照がエラーになる

おそらくEclipse JDTのエラーだと思われる。以下のバージョンで確認した。

  • Version: 2019-03 (4.11.0) Eclipse Java Development Tools 3.17.0.v20190307-0500
  • Version: 2019-06 (4.12.0) Eclipse Java Development Tools 3.18.0.v20190605-1800

問題

OxygenでJava8を使っていた時には問題がなかったのだが、Eclipse-2019-03、2019/06のJDT上でエラーになってしまう。javacでは警告が出るものの問題無くコンパイルできる。以下のようなコードだ。

※JDK Complianceは1.8にしてある。

import java.util.function.*;

public class Sample {

  class Parent<T> {
    class Event {      
    }
  }

  class Child extends Parent<String> {
  }

  Child child = new Child();

  void foo() {
    listen(Child.Event.class, this::bar); // ここがエラーになる
  }

  void bar(Child.Event e) {    
  }

  <T>void listen(Class<T>clazz, Consumer<T>consumer) {    
  }
}

エラー内容としては以下だ。

Multiple markers at this line
    - The type Sample does not define bar(T) that is applicable here
    - The method listen(Class<T>, Consumer<T>) in the type Sample is not applicable for 
     the arguments (Class<Sample.Parent.Event>, this::bar)

javacでコンパイル

しかし、実際にはjavacでも警告は出る。Eclipse JDTがエラーにしてしまうこと自体はjavacのふるまいと一致しない。

Java8でコンパイルしてみる

"C:\Program Files\Java\jdk1.8.0_201\bin\javac" -J-Duser.language=en -Xlint:unchecked Sample.java
Sample.java:18: warning: [unchecked] unchecked method invocation: method listen in class Sample is applied to given types
    listen(Child.Event.class, this::bar);
          ^
  required: Class<T>,Consumer<T>
  found: Class<Sample.Parent.Event>,Consumer<Sample.Parent.Event>
  where T is a type-variable:
    T extends Object declared in method <T>listen(Class<T>,Consumer<T>)
1 warning

Java12でコンパイルしてみる

"C:\Program Files\AdoptOpenJDK\jdk-12.0.1.12-hotspot\bin\javac" -J-Duser.language=en -target 1.8 -source 1.8 -Xlint:unchecked Sample.java
warning: [options] bootstrap class path not set in conjunction with -source 8
Sample.java:18: warning: [unchecked] unchecked method invocation: method listen in class Sample is applied to given types
    listen(Child.Event.class, this::bar);
          ^
  required: Class<T>,Consumer<T>
  found: Class<Sample.Parent.Event>,Consumer<Sample.Parent.Event>
  where T is a type-variable:
    T extends Object declared in method <T>listen(Class<T>,Consumer<T>)
2 warnings

解決策

Eclipse上でエラーではなくWarningに変更する

ことができれば良いのだが、こういったオプションは見つからなかった。

メソッド参照ではなくラムダ式に変更

以下に変えるとエラーは無くなる。

    listen(Child.Event.class, e->bar(e));

しかしEclipse上での警告は出る。

Type safety: The expression of type Sample.Parent.Event needs unchecked conversion to conform to Sample.Parent<String>.Event