Questa è una debolezza nel meccanismo di inferenza del tipo del compilatore. Per dedurre il tipo di ulambda, è 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 Functionche accetta un Userargomento. Quindi nel lambda sulla prima riga, udeve essere di tipo Usere 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 uche 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.