Comparator.reversed() 不使用 lambda 编译 [英] Comparator.reversed() does not compile using lambda

查看:23
本文介绍了Comparator.reversed() 不使用 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

错误:

comjava8collectionapiCollectionTest.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 类型的参数.在第一行,Comparator.comparing() 需要返回Comparator.这意味着 Comparator.comparing() 需要一个带有 User 参数的 Function.因此,在第一行的 lambda 中,u 必须是 User 类型并且一切正常.

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 所以看起来目标类型应该传播回接收器,但它不是.(就像我说的,这是一个弱点.)

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 推断为 Object(最后的推理回退),结果失败.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆