+-
java – Comparator.reversed()不使用lambda编译
我有一个包含一些User对象的列表,我正在尝试对列表进行排序,但只能使用方法引用,使用lambda表达式,编译器会给出错误:

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()需要一个带有User参数的Function.因此,在第一行的lambda中,你必须是User类型,一切正常.

在第二行和第三行中,目标类型由于对reverse()的调用而中断.我不完全确定为什么;反向()的接收器和返回类型都是比较器< T>.因此看起来目标类型应该传播回接收器,但事实并非如此. (就像我说的,这是一个弱点.)

在第二行中,方法参考提供了填补这一空白的其他类型信息.第三行中没有此信息,因此编译器会将u推断为Object(最后的推理回退),但失败了.

显然,如果你可以使用方法参考,那么这样做就可以了.有时您不能使用方法引用,例如,如果要传递其他参数,则必须使用lambda表达式.在这种情况下,您将在lambda中提供显式参数类型:

userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());

可能有可能在将来的版本中增强编译器以涵盖这种情况.

点击查看更多相关文章

转载注明原文:java – Comparator.reversed()不使用lambda编译 - 乐贴网