Comparator.reversed()不使用lambda进行编译 [英] Comparator.reversed() does not compile using lambda
问题描述
我有一个包含一些User对象的列表,我正在尝试对列表进行排序,但只能使用方法引用,使用lambda表达式,编译器会给出错误:
I have a list with some User objects and i'm trying to sort the list, but only works using method reference, with lambda expression the compiler gives an error:
List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error
错误:
com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
userList.sort(Comparator.comparing(u -> u.getName()).reversed());
^
symbol: method getName()
location: variable u of type Object
1 error
推荐答案
这是编译器类型推理机制的一个弱点。为了推断lambda中 u
的类型,需要建立lambda的目标类型。这完成如下。 userList.sort()
期望参数类型为 Comparator< User>
。在第一行中, Comparator.comparing()
需要返回 Comparator< User>
。这意味着 Comparator.comparing()
需要一个函数
,需要用户
参数。因此,在第一行的lambda中, u
必须是用户
类型,一切正常。
This is a weakness in the compiler's type inferencing mechanism. In order to infer the type of u
in the lambda, the target type for the lambda needs to be established. This is accomplished as follows. userList.sort()
is expecting an argument of type Comparator<User>
. In the first line, Comparator.comparing()
needs to return Comparator<User>
. This implies that Comparator.comparing()
needs a Function
that takes a User
argument. Thus in the lambda on the first line, u
must be of type User
and everything works.
在第二行和第三行中,由于存在对 reversed()
的调用,目标类型被中断。我不完全确定为什么;收件人和返回类型 reversed()
都是 Comparator< T>
所以它似乎应该是目标类型被传播回接收器,但事实并非如此。 (就像我说的那样,这是一个弱点。)
In the second and third lines, the target typing is disrupted by the presence of the call to reversed()
. I'm not entirely sure why; both the receiver and the return type of reversed()
are Comparator<T>
so it seems like the target type should be propagated back to the receiver, but it isn't. (Like I said, it's a weakness.)
在第二行中,方法参考提供了填补这一空白的其他类型信息。第三行没有此信息,因此编译器推断 u
为对象
(最后的推理回退) ),失败。
In the second line, the method reference provides additional type information that fills this gap. This information is absent from the third line, so the compiler infers u
to be Object
(the inference fallback of last resort), which fails.
显然,如果你可以使用方法参考,那么这样做就可以了。有时您不能使用方法引用,例如,如果要传递其他参数,则必须使用lambda表达式。在这种情况下,您将在lambda中提供显式参数类型:
Obviously if you can use a method reference, do that and it'll work. Sometimes you can't use a method reference, e.g., if you want to pass an additional parameter, so you have to use a lambda expression. In that case you'd provide an explicit parameter type in the lambda:
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
在将来的版本中,可能会增强编译器以涵盖这种情况。
It might be possible for the compiler to be enhanced to cover this case in a future release.
这篇关于Comparator.reversed()不使用lambda进行编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!