Esta é uma fraqueza no mecanismo de inferência de tipo do compilador. Para inferir o tipo de u
no lambda, o tipo de destino para o lambda precisa ser estabelecido. Isso é feito da seguinte maneira. userList.sort()
está esperando um argumento do tipo Comparator<User>
. Na primeira linha, Comparator.comparing()
precisa retornar Comparator<User>
. Isso implica que Comparator.comparing()
precisa de Function
um User
argumento. Assim no lambda da primeira linha, u
deve ser do tipo User
e tudo funciona.
Na segunda e terceira linhas, a digitação do destino é interrompida pela presença da chamada para reversed()
. Não tenho certeza do porquê; tanto o receptor quanto o tipo de retorno reversed()
são, Comparator<T>
então parece que o tipo de destino deveria ser propagado de volta para o receptor, mas não é. (Como eu disse, é uma fraqueza.)
Na segunda linha, a referência do método fornece informações de tipo adicionais que preenchem essa lacuna. Essas informações estão ausentes na terceira linha, portanto, o compilador infere u
ser Object
(o fallback de inferência de último recurso), o que falha.
Obviamente, se você pode usar uma referência de método, faça isso e funcionará. Às vezes, você não pode usar uma referência de método, por exemplo, se quiser passar um parâmetro adicional, então você tem que usar uma expressão lambda. Nesse caso, você forneceria um tipo de parâmetro explícito no lambda:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Pode ser possível que o compilador seja aprimorado para cobrir esse caso em uma versão futura.