Questa è una debolezza nel meccanismo di inferenza del tipo del compilatore. Per dedurre il tipo di u
lambda, è necessario stabilire il tipo di destinazione per lambda. Ciò si ottiene come segue. userList.sort()
si aspetta un argomento di tipo Comparator<User>
. Nella prima riga, Comparator.comparing()
deve tornare Comparator<User>
. Ciò implica che Comparator.comparing()
necessita di una Function
che accetta un User
argomento. Quindi nel lambda sulla prima riga, u
deve essere di tipo User
e tutto funziona.
Nella seconda e terza riga, la digitazione del target è interrotta dalla presenza della chiamata a reversed()
. Non sono del tutto sicuro del perché; sia il ricevitore che il tipo di ritorno reversed()
sono Comparator<T>
così sembra che il tipo di destinazione dovrebbe essere propagato al ricevitore, ma non lo è. (Come ho detto, è una debolezza.)
Nella seconda riga, il riferimento al metodo fornisce ulteriori informazioni sul tipo che colmano questa lacuna. Questa informazione è assente dalla terza riga, quindi il compilatore deduce u
che sia Object
(l'inferenza fallback di ultima istanza), che fallisce.
Ovviamente se puoi usare un metodo di riferimento, fallo e funzionerà. A volte non è possibile utilizzare un riferimento al metodo, ad esempio, se si desidera passare un parametro aggiuntivo, quindi è necessario utilizzare un'espressione lambda. In tal caso, forniresti un tipo di parametro esplicito nel lambda:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Potrebbe essere possibile migliorare il compilatore per coprire questo caso in una versione futura.