Это слабое место в механизме определения типа компилятора. Чтобы определить тип u
лямбды, необходимо установить целевой тип лямбды. Это осуществляется следующим образом. userList.sort()
ожидает аргумент типа Comparator<User>
. В первой строке Comparator.comparing()
нужно вернуть Comparator<User>
. Это означает , что Comparator.comparing()
нуждается в Function
том , что принимает User
аргумент. Таким образом, лямбда в первой строке u
должна быть типа, User
и все работает.
Во второй и третьей строках целевой набор текста нарушается присутствием вызова reversed()
. Я не совсем уверен, почему; и получатель, и тип возвращаемого значения reversed()
таковы, Comparator<T>
поэтому кажется, что целевой тип должен быть передан обратно получателю, но это не так. (Как я уже сказал, это слабость.)
Во второй строке ссылка на метод предоставляет дополнительную информацию о типе, которая заполняет этот пробел. Эта информация отсутствует в третьей строке, так что компилятор выводит u
быть Object
(запасным вариантом логического вывода последней инстанции), которая выходит из строя.
Очевидно, что если вы можете использовать ссылку на метод, сделайте это, и это сработает. Иногда вы не можете использовать ссылку на метод, например, если вы хотите передать дополнительный параметр, поэтому вам нужно использовать лямбда-выражение. В этом случае вы должны указать явный тип параметра в лямбде:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Возможно, компилятор будет расширен, чтобы охватить этот случай в будущем выпуске.