我认为即使谓词无效,Stream.filter() 也不会显示编译时错误

I think that the Stream.filter() is not showing compile time error even with an invalid predicate

在下面的代码中我有这一行:stream.filter(Data::isEven); 我正在使用 filter() 并且 filter() 接受 Predicate 接口作为参数。我们都知道 Predicate 有一个带有签名的方法:public boolean test(T t); 它接受一个参数和 returns 一个布尔值。

我的理解是 isEven() 不接受参数的方法不是有效的谓词,因为与 test() 方法不同,它不接受任何参数,所以为什么我的代码没有显示编译时错误?

import java.util.stream.Stream;

public class Main App {


    public static void main(String args[]) {

        Stream<Data> stream =
                Stream.of(new Data(4), new Data(1));

        stream.filter(Data::isEven); // should throw compile error but doesn't
    }

}


class Data{
    int i;
    public Data(int i) {
        this.i=i;
    }
    public boolean isEven() {
        return i%2==0;
    }
}

问题在于 Data::isEven 是等同于 data -> data.isEven() 谓词的方法引用:

Predicate<Data> predicate = data -> data.isEven();
// is the same as
Predicate<Data> predicate= Data::isEven;

这在JLS 15.13中有描述:

The target reference of an instance method (§15.12.4.1) may be provided by the method reference expression using an ExpressionName, a Primary, or super, or it may be provided later when the method is invoked.

....

Evaluation of a method reference expression produces an instance of a functional interface type (§9.8). Method reference evaluation does not cause the execution of the corresponding method; instead, this may occur at a later time when an appropriate method of the functional interface is invoked.

在您的例子中,Data::isEven 是对 Data 对象的实例方法 isEven 的引用。

Data::isEvenPredicate.

要调用此方法,您必须传递值,例如:myData.isEven()。 这与 isEven(myData) 相同。所以区别仅在于语法(参数在点之前或括号内),但在语义上是相同的。

因此 isEvenPredicate<Data> 因为它接受 Data 和 returns Boolean.

As others wrote "Data::isEven" or "data -> data.isEven()" 在这里是谓词。当我们调用这个谓词的 test 方法时,我们将 data 的实例(你有一个这样的实例流)作为参数传递给那里。