Angenommen, ich habe eine generische Schnittstelle:
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
Und eine Methode sort
:
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable<T> comp) {
// sort the list
}
Ich kann diese Methode aufrufen und einen Lambda-Ausdruck als Argument übergeben:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Das wird gut funktionieren.
Aber jetzt, wenn ich die Schnittstelle nicht generisch und die Methode generisch mache:
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) {
}
Und rufen Sie dann Folgendes auf:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Es wird nicht kompiliert. Es zeigt einen Fehler beim Lambda-Ausdruck, der sagt:
"Zielmethode ist generisch"
OK, wenn ich es mit kompiliert habe javac
, wird folgender Fehler angezeigt:
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
Aus dieser Fehlermeldung geht hervor, dass der Compiler die Typargumente nicht ableiten kann. Ist das der Fall? Wenn ja, warum passiert das dann so?
Ich habe verschiedene Möglichkeiten ausprobiert und über das Internet gesucht. Dann habe ich diesen JavaCodeGeeks-Artikel gefunden , der einen Weg zeigt, also habe ich versucht:
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
was wiederum nicht funktioniert, im Gegensatz zu dem, was dieser Artikel behauptet, dass es funktioniert. Möglicherweise funktionierte es in einigen ersten Builds.
Meine Frage lautet also: Gibt es eine Möglichkeit, einen Lambda-Ausdruck für eine generische Methode zu erstellen? Ich kann dies jedoch mithilfe einer Methodenreferenz tun, indem ich eine Methode erstelle:
public static <T extends Comparable<T>> int compare(T obj1, T obj2) {
return obj1.compareTo(obj2);
}
in einer Klasse sagen SO
und weitergeben als:
sort(list, SO::compare);