Esta es una debilidad en el mecanismo de inferencia de tipos del compilador. Para inferir el tipo de u
en la lambda, es necesario establecer el tipo de destino de la lambda. Esto se logra de la siguiente manera. userList.sort()
espera un argumento de tipo Comparator<User>
. En la primera línea, Comparator.comparing()
debe regresar Comparator<User>
. Esto implica que Comparator.comparing()
necesita Function
un User
argumento. Por lo tanto, en la lambda de la primera línea, u
debe ser de tipo User
y todo funciona.
En la segunda y tercera líneas, la escritura de destino se ve interrumpida por la presencia de la llamada a reversed()
. No estoy completamente seguro de por qué; tanto el receptor como el tipo de retorno de reversed()
son, Comparator<T>
por lo que parece que el tipo de destino debería propagarse de regreso al receptor, pero no lo es. (Como dije, es una debilidad).
En la segunda línea, la referencia del método proporciona información de tipo adicional que llena este vacío. Esta información está ausente en la tercera línea, por lo que el compilador infiere u
que es Object
(la reserva de inferencia de último recurso), que falla.
Obviamente, si puede usar una referencia de método, hágalo y funcionará. A veces no puede usar una referencia de método, por ejemplo, si desea pasar un parámetro adicional, por lo que debe usar una expresión lambda. En ese caso, proporcionaría un tipo de parámetro explícito en el lambda:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Es posible que el compilador se mejore para cubrir este caso en una versión futura.