Dies ist eine Schwachstelle im Typinferenzmechanismus des Compilers. Um auf den u
Lambda- Typ schließen zu können , muss der Zieltyp für das Lambda festgelegt werden. Dies wird wie folgt erreicht. userList.sort()
erwartet ein Argument vom Typ Comparator<User>
. In der ersten Zeile Comparator.comparing()
muss zurückkehren Comparator<User>
. Dies bedeutet , dass Comparator.comparing()
muss ein , Function
die eine nimmt User
Argument. Somit muss im Lambda in der ersten Zeile u
vom Typ seinUser
und alles funktioniert.
In der zweiten und dritten Zeile wird die Zieleingabe durch das Vorhandensein des Anrufs an unterbrochen reversed()
. Ich bin mir nicht ganz sicher warum; Sowohl der Empfänger als auch der Rückgabetyp von reversed()
sind Comparator<T>
so, dass es so aussieht, als ob der Zieltyp an den Empfänger zurückgegeben werden sollte, aber dies ist nicht der Fall. (Wie ich schon sagte, es ist eine Schwäche.)
In der zweiten Zeile enthält die Methodenreferenz zusätzliche Typinformationen, die diese Lücke füllen. Diese Informationen fehlen in der dritten Zeile, sodass der Compiler darauf schließen u
kann Object
(der Inferenz-Fallback des letzten Auswegs), was fehlschlägt.
Wenn Sie eine Methodenreferenz verwenden können, tun Sie dies natürlich und es wird funktionieren. Manchmal können Sie keine Methodenreferenz verwenden, z. B. wenn Sie einen zusätzlichen Parameter übergeben möchten, sodass Sie einen Lambda-Ausdruck verwenden müssen. In diesem Fall würden Sie im Lambda einen expliziten Parametertyp angeben:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Möglicherweise kann der Compiler erweitert werden, um diesen Fall in einer zukünftigen Version abzudecken.