实例方法引用和Lambda参数

13 浏览
0 Comments

实例方法引用和Lambda参数

我对方法引用的语法有些困惑,其中有两个参数a和b,并且引用的是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有三个或更多的参数,那么是合法的吗?第一个参数是否成为方法的目标,剩下的参数是否成为方法的参数?

0
0 Comments

问题的出现原因是对于lambda表达式中的方法引用,如果被引用的方法是实例方法,那么在运行时,如何确定方法的目标引用以及方法的参数。解决方法是在Java语言规范的第15.13.3节中进行了详细说明。

根据Java语言规范的15.13.3节的规定,如果方法引用的形式是"ReferenceType :: [TypeArguments] Identifier",那么在运行时,方法引用的效果类似于编译时声明的方法调用表达式。方法调用表达式的运行时评估遵循规范中的相应规则。

在方法调用表达式的运行时评估中,需要根据编译时声明的方法引用表达式来确定调用模式。如果编译时声明是一个实例方法,那么调用模式的目标引用就是调用方法的第一个形式参数;否则,没有目标引用。

另外,如果编译时声明是一个实例方法,那么方法调用表达式的参数(如果有的话)就是调用方法的第二个及以后的形式参数;否则,方法调用表达式的参数就是调用方法的形式参数。

因此,对于lambda表达式中的方法引用,如果被引用的方法是实例方法,那么第一个参数就是方法的目标引用,而剩下的参数就是方法的参数。

例如,如果lambda表达式中有三个或更多参数,那么第一个参数将成为方法的目标引用,而剩下的参数将成为方法的参数。

这样的规定使得lambda表达式中的方法引用更加灵活,能够处理各种不同参数个数的情况。

0
0 Comments

Instance Method Reference and Lambda Parameters

在Java 8中,我们可以使用方法引用来简化Lambda表达式的写法。然而,有时候在使用方法引用时,我们可能会遇到一些问题。

一个常见的问题是,当我们使用方法引用引用实例方法时,Lambda表达式的参数数量可能会有所不同。这是因为方法引用会被转换成一个Lambda表达式,而Lambda表达式需要根据上下文来确定参数的数量。

假设我们需要一个对字符串进行比较的Comparator实例的引用。我们可以这样写:

.sorted(String::compareTo)

这里,String::compareTo与下面的Lambda表达式是等价的:

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

这是因为方法引用会被转换成一个Lambda表达式,而Lambda表达式需要两个参数。第一个参数是流中的任意对象,第二个参数是Comparator的compare方法所需要的参数。

另一个例子是使用方法引用获取员工的薪水:

.map(Employee::getSalary)

在这个例子中,map方法需要一个Function作为参数。Function接口定义了一个apply方法,该方法有一个参数。在这个例子中,Lambda表达式只需要一个参数,即Employee实例。

总之,在编译时的上下文中,方法引用会被转换成一个Lambda表达式,该Lambda表达式的参数数量取决于目标方法所需的参数数量。第一个参数是实例对象本身,后面的参数是目标方法所需的参数,参数的顺序与目标方法的参数顺序相同。

0