Il s'agit d'une faiblesse dans le mécanisme d'inférence de type du compilateur. Afin de déduire le type de u
dans le lambda, le type de cible pour le lambda doit être établi. Ceci est accompli comme suit. userList.sort()
attend un argument de type Comparator<User>
. Dans la première ligne, Comparator.comparing()
doit revenir Comparator<User>
. Cela implique qu'il Comparator.comparing()
faut un Function
qui prend un User
argument. Ainsi, dans le lambda sur la première ligne, u
doit être de type User
et tout fonctionne.
Dans les deuxième et troisième lignes, la saisie de la cible est perturbée par la présence de l'appel à reversed()
. Je ne sais pas exactement pourquoi; le récepteur et le type de retour de reversed()
sont Comparator<T>
donc il semble que le type de cible devrait être propagé vers le récepteur, mais ce n'est pas le cas. (Comme je l'ai dit, c'est une faiblesse.)
Dans la deuxième ligne, la référence de méthode fournit des informations de type supplémentaires qui comblent cette lacune. Cette information est absente de la troisième ligne, donc le compilateur en déduit u
être Object
(le repli d'inférence de dernier recours), qui échoue.
Évidemment, si vous pouvez utiliser une référence de méthode, faites-le et cela fonctionnera. Parfois, vous ne pouvez pas utiliser une référence de méthode, par exemple, si vous souhaitez passer un paramètre supplémentaire, vous devez donc utiliser une expression lambda. Dans ce cas, vous fournirez un type de paramètre explicite dans le lambda:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
Il est possible que le compilateur soit amélioré pour couvrir ce cas dans une version ultérieure.