实例方法引用和Lambda参数

我无法理解方法引用的语法,其中有两个参数ab ,引用是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); 

我没有find一个规则来replace语法: a.method(b)与方法引用。

例如,如果lambda有三个或更多的参数呢? 这是合法吗? 第一个参数是否成为方法目标,剩下的成为参数?

我想你正在寻找JLS第15.13.3节 ,其中包括:

如果表单是ReferenceType :: [TypeArguments] Identifier ,则调用方法的主体同样具有方法调用expression式对编译时声明的影响,该编译时声明是方法引用expression式的编译时声明。 方法调用expression式的运行时评估如第15.12.4.3节,第15.12.4.4节和第15.12.4.5节所述,其中:

  • 调用模式是从第15.12.3节中规定的编译时声明派生的。

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

  • 如果编译时声明是一个实例方法,那么方法调用expression式的参数(如果有的话)是调用方法的第二个和随后的forms参数。 否则,方法调用expression式的参数是调用方法的forms参数。

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

例如,如果lambda有三个或更多的参数呢? 这是合法吗? 第一个参数是否成为方法目标,剩下的成为参数?

对 :)

我将在这里举几个例子,对于那些发现Oracle文档有点困难的人来说。想象一下你需要一个Comparator实例的引用:

 .sorted(String::compareTo) 

String :: compareTo与以下内容相同:

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

因为,正如乔恩解释,一个方法的引用将被转换为一个lambda,将期望2个参数。 在stream中传入的实际任意对象作为第一个参数,还有一个参数(因为Comparator期望int compare(T o1, T o2) )。 另一个案例:

 .map(Employee::getSalary) 

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

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