Comparator.reversed()不使用lambda进行编译

Comparator.reversed()不使用lambda进行编译

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

List<User> userList = Arrays.asList(u1, u2, u3);userList.sort(Comparator.comparing(u -> u.getName())); // worksuserList.sort(Comparator.comparing(User::getName).reversed()); // worksuserList.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 Object1 error


阿晨1998
浏览 2637回答 2
2回答

慕少森

这是编译器类型推理机制的一个弱点。为了推断ulambda中的类型,需要建立lambda的目标类型。这完成如下。userList.sort()期待一种类型的论证Comparator<User>。在第一行,Comparator.comparing()需要返回Comparator<User>。这意味着Comparator.comparing()需要Function采用一个User参数。因此,在第一行的lambda中,u必须是类型User,一切正常。在第二行和第三行中,目标类型由于存在调用而中断reversed()。我不完全确定为什么;&nbsp;接收器和返回类型reversed()都是Comparator<T>如此,似乎目标类型应该传播回接收器,但事实并非如此。(就像我说的,这是一个弱点。)在第二行中,方法参考提供了填补这一空白的其他类型信息。此信息是从第三行不存在,所以编译器推断u是Object(不得已的推论回退),这将失败。显然,如果你可以使用方法参考,那么这样做就可以了。有时您不能使用方法引用,例如,如果要传递其他参数,则必须使用lambda表达式。在这种情况下,您将在lambda中提供显式参数类型:userList.sort(Comparator.comparing((User&nbsp;u)&nbsp;->&nbsp;u.getName()).reversed());可能有可能在将来的版本中增强编译器以涵盖这种情况。

长风秋雁

您可以通过使用Comparator.comparing带有Comparator.reverseOrder()第二个参数的双参数来解决此限制:users.sort(comparing(User::getName,&nbsp;reverseOrder()));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java