Lambda-Ausdruck und generische Methode
Angenommen, ich habe eine generische Schnittstelle:
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
Sowie eine Methode sort
:
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable<T> comp) {
//sort the list
}
Kann ich aufrufen dieser Methode, und übergeben Sie einen lambda-Ausdruck als argument:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Dass wird gut funktionieren.
Aber jetzt, wenn ich das interface nicht generisch, und die generische Methode:
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 dann aufrufen wie:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Es nicht kompilieren. Es zeigt Fehler an der lambda-Ausdruck sagen:
"Target Methode ist generisch"
OK, wenn ich es kompiliert mit javac
es zeigt folgenden Fehler:
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, es scheint, wie compiler ist nicht in der Lage zu folgern, die Art der Argumente. Ist das der Fall? Wenn ja, dann warum ist es passiert wie diesem?
Ich habe versucht, verschiedene Möglichkeiten, gesucht über das internet. Dann fand ich diese JavaCodeGeeks Artikel, die zeigt ein Weg, so habe ich versucht:
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
was mal wieder nicht funktioniert, im Gegensatz zu dem, was dieser Artikel behauptet, dass es funktioniert. Könnte möglich sein, dass es früher in einigen anfänglichen baut.
Also meine Frage ist: gibt es eine Möglichkeit zu schaffen lambda-Ausdruck für eine generische Methode? Ich kann dies mithilfe einer Methode, Referenz, obwohl, durch die Schaffung einer Methode:
public static <T extends Comparable<T>> int compare(T obj1, T obj2) {
return obj1.compareTo(obj2);
}
Klasse sagen SO
, und übergeben Sie es als:
sort(list, SO::compare);
InformationsquelleAutor Rohit Jain | 2014-03-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie nicht verwenden, eine lambda-Ausdruck für eine funktionale Schnittstelle, wenn die Methode in der funktionale Schnittstelle hat Typ-Parameter. Sehen §15.27.3 in JLS8:
Ich bin sicher, es gibt einen guten Grund für diese Einschränkung. Was ist es?
es gibt einfach keine syntax für die Deklaration Typ-Parameter eines lambda-Ausdrucks. Und so einem würde die syntax sehr kompliziert sein. Beachten Sie, dass der parser noch in der Lage sein müssen zu sagen, wie ein lambda-Ausdruck mit Typ-Parametern abgesehen von anderen rechtlichen Java-Konstrukte. So haben Sie Rückgriff auf die Methode verweist. Das Ziel der Methode kann deklarieren, geben Sie Parameter mithilfe eines etablierten syntax.
noch, wo Typ-Parameter kann automatisch abgeleitet, der compiler könnte decude ein capure Art, wie es tut, wenn Sie erklären, z.B.<?> und tun, Typ-checks, mit denen erfasste Arten. Sicher, das macht es unmöglich, geben Sie als Typ-Parameter in den Körper, aber wenn Sie müssten, dass der Rückgriff auf die Methode verweist, wird eine gute alternative ist
InformationsquelleAutor nosid
Unter Verwendung der Methode Referenz, ich fand andere Weise übergeben das argument:
InformationsquelleAutor Andrey
Nur Punkt-compiler die richtige version von generischen Komparator mit
(Comparator<String>)
Also die Antwort wird sein,
sort(list, (Comparator<String>)(a, b) -> a.compareTo(b));
incompatible types: java.util.Comparator<java.lang.String> cannot be converted to MyComparable
undMyComparable
ist nicht generisch (kein Typ), so(MyComparable<String>)
würde auch nicht funktionierenWeiß nicht, wie Sie Tippen den code @CarlosHeuberger, aber es funktioniert für mich sehr gut, das ist das, was ich suchte.
nach 2 Monaten... ich kopiert&eingefügt mit dem code und kopiert&eingefügte Zeile oben über Ihre Art der Linie - nur, dass, wie hier: ideone.com/YNwBbF ! Sind Sie sicher, dass Sie getan haben geben Sie oben stehenden code genau? mit
Compartor
?Nein ich nicht, ich die Idee, die hinter der Antwort, die Besetzung der funktionalen sagen das kompilieren, welche Art es ist und es hat funktioniert.
gut, und was ist Ihr problem mit meinem "eingeben"? Die Antwort ist, wie es geschrieben ist, funktioniert nicht.
InformationsquelleAutor Aleч
Du meinst so etwas?:
Welcher Art ist diese lambda? Sie konnte es nicht Ausdrücken in Java und kann deshalb nicht Komponieren dieser Ausdruck in einer Funktion, die Anwendung und Ausdrücke werden zusammensetzbar.
Hierzu müssen wir arbeiten, würden Sie brauchen Unterstützung für Rank2 Typen in Java.
Methoden sind zulässig, um generisch sein, aber deshalb konnte man Sie nicht verwenden Sie Sie als Ausdruck. Sie können jedoch reduziert werden, um die lambda expression, die durch Spezialisierung alle notwendigen generischen Typen, bevor Sie Sie weitergeben:
ClassName::<TypeName>methodName
InformationsquelleAutor iconfly