实例方法引用和Lambda参数
我无法理解方法引用的语法,其中有两个参数a
和b
,引用是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期望该对象作为第一个参数+目标方法需要的任意数量的参数以相同的对应顺序。