Esta é uma fraqueza no mecanismo de inferência de tipo do compilador. Para inferir o tipo de uno 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 Functionum Userargumento. Assim no lambda da primeira linha, udeve ser do tipo Usere 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 user 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.