实例方法参考和Lambda参数

时间:2014-08-26 18:16:09

标签: java lambda java-8 closures method-reference

我无法理解方法引用的语法,其中有两个参数ab,引用的是a 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有三个或更多参数怎么办?这合法吗?第一个参数是否成为方法目标,其余参数是否为参数?

2 个答案:

答案 0 :(得分:7)

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

  

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

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

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

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

  •   

注意最后两个子弹,基本上。

  

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

是的:)

答案 1 :(得分: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)

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

总结 - 取决于编译时上下文,对任意对象的方法引用将始终“转换”为lambda,该lambda期望该对象作为第一个参数+目标方法在相同对应中需要的任意数量的参数顺序。