7

我无法理解方法引用的语法,其中有两个参数ab,并且引用是对aon的方法b

例如,我了解如何

Arrays.sort(personArray, comparators::compareByName);

相当于

Arrays.sort(personArray, (o1, o2) -> comparators.compareByName(o1, o2));

因为在这种情况下,lambda 参数与方法调用参数匹配(o1, o2)

但是对于这个 lambda

stream.sorted((o1, o2) -> o1.compareToIgnoreCase(o2));

我的 IDE 告诉我这相当于:

stream.sorted(String::compareToIgnoreCase);

而且我没有找到替换该语法的规则:a.method(b)使用方法参考。

例如,如果 lambda 有三个或更多参数怎么办?那合法吗?第一个参数是否成为方法目标,其余的成为参数?

4

2 回答 2

7

我认为您正在寻找JLS 第 15.13.3 节,其中包括:

如果形式是ReferenceType :: [TypeArguments] Identifier,则调用方法的主体同样具有编译时声明的方法调用表达式的效果,该声明是方法引用表达式的编译时声明。方法调用表达式的运行时评估在 §15.12.4.3、§15.12.4.4 和 §15.12.4.5 中指定,其中:

  • 调用模式派生自 §15.12.3 中指定的编译时声明。

  • 如果编译时声明是实例方法,则目标引用是调用方法的第一个形参。否则,没有目标参考。

  • 如果编译时声明是实例方法,则方法调用表达式的参数(如果有)是调用方法的第二个和后续形式参数。否则,方法调用表达式的参数是调用方法的形式参数。

基本上,请注意最后两个项目符号。

例如,如果 lambda 有三个或更多参数怎么办?那合法吗?第一个参数是否成为方法目标,其余的成为参数?

是的 :)

于 2014-08-26T18:20:57.380 回答
1

对于那些觉得 Oracle 文档有点难以理解的人,我将在这里举几个例子。假设您需要一个对 Comparator 实例的引用:

.sorted(String::compareTo)

String::compareTo 等同于:

(String a, String b) -> a.compareTo(b);

因为,正如 Jon 解释的那样,方法引用将被转换为需要 2 个参数的 lambda。在流中作为第一个参数传递的实际任意对象,还有一个参数(因为 Comparator 需要int compare(T o1, T o2))。另一个案例:

.map(Employee::getSalary)

在这种情况下,地图需要:功能。函数需要实现R apply(T var1)- 具有 1 个参数的方法。在这种情况下,将传递给 lambda 的唯一参数是实际的任意对象 - Employee 上的实例。

总而言之 - 根据编译时上下文,对任意对象的方法引用将始终被“转换”为 lambda,该 lambda 期望该对象作为第一个参数 + 目标方法以相同的相应顺序需要的任意数量的参数。

于 2017-02-09T16:29:42.153 回答