私が一般的なインターフェースを持っているとしましょう:
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
そして方法sort
:
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable<T> comp) {
// sort the list
}
このメソッドを呼び出して、ラムダ式を引数として渡すことができます。
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
それはうまくいきます。
しかし、インターフェイスをジェネリックにせず、メソッドをジェネリックにすると、次のようになります。
interface MyComparable {
public <T extends Comparable<T>> int compare(T obj1, T obj2);
}
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable comp) {
}
そして、これを次のように呼び出します:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
コンパイルされません。それはラムダ式でのエラーを示しています:
「ターゲットメソッドはジェネリック」
OK、を使用してコンパイルするとjavac
、次のエラーが表示されます。
SO.java:20: error: incompatible types: cannot infer type-variable(s) T#1
sort(list, (a, b) -> a.compareTo(b));
^
(argument mismatch; invalid functional descriptor for lambda expression
method <T#2>(T#2,T#2)int in interface MyComparable is generic)
where T#1,T#2 are type-variables:
T#1 extends Comparable<T#1> declared in method <T#1>sort(List<T#1>,MyComparable)
T#2 extends Comparable<T#2> declared in method <T#2>compare(T#2,T#2)
1 error
このエラーメッセージから、コンパイラーが型引数を推測できないようです。それは事実ですか?はいの場合、なぜこのようになっているのですか?
インターネットでいろいろな方法で検索してみました。次に、方法を示すこのJavaCodeGeeks記事を見つけたので、試してみました。
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
これは、その記事がそれが機能すると主張していることとは対照的に、再び機能しません。一部の初期ビルドで機能していた可能性があります。
だから私の質問です:ジェネリックメソッドのラムダ式を作成する方法はありますか?ただし、メソッドを作成することで、メソッド参照を使用してこれを行うことができます。
public static <T extends Comparable<T>> int compare(T obj1, T obj2) {
return obj1.compareTo(obj2);
}
一部のクラスではと言いSO
、次のように渡します。
sort(list, SO::compare);