Java 我认为Stream.filter()即使使用了无效的谓词,也没有显示编译时错误

Java 我认为Stream.filter()即使使用了无效的谓词,也没有显示编译时错误,java,lambda,java-8,java-stream,method-reference,Java,Lambda,Java 8,Java Stream,Method Reference,在下面的代码中,我有一行:stream.filter(Data::isEven) 我正在使用一个filter()和一个filter()接受一个谓词接口作为参数。我们都知道,谓词有一个带有签名的方法:公共布尔测试(T) 它接受一个参数并返回一个布尔值 我理解不接受任何参数的isEven()方法不是有效的谓词,因为与test()方法不同,它不接受任何参数,所以为什么我的代码没有显示编译时错误 import java.util.stream.Stream; public class Main App

在下面的代码中,我有一行:
stream.filter(Data::isEven)
我正在使用一个
filter()
和一个
filter()
接受一个
谓词
接口作为参数。我们都知道,
谓词
有一个带有签名的方法:
公共布尔测试(T)
它接受一个参数并返回一个布尔值

我理解不接受任何参数的
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;
    }
}
import java.util.stream.stream;
公共类主应用程序{
公共静态void main(字符串参数[]){
溪流=
流(新数据(4)、新数据(1));
stream.filter(Data::isEven);//应该抛出编译错误,但不会
}
}
类数据{
int i;
公共数据(int i){
这个。i=i;
}
公共布尔值isEven(){
返回i%2==0;
}
}

问题是
Data::isEven
是一个方法引用,相当于
Data->Data.isEven()
谓词:

Predicate<Data> predicate = data -> data.isEven();
// is the same as
Predicate<Data> predicate= Data::isEven;
Predicate=data->data.isEven();
//与
谓词=数据::isEven;
这在以下章节中进行了描述:

实例方法(§15.12.4.1)的目标引用可由方法引用表达式使用
ExpressionName
Primary
super
提供,也可在调用该方法后提供

方法引用表达式的求值产生函数接口类型的实例(§9.8)。方法参考评估不会导致相应方法的执行;相反,这可能会在稍后调用函数接口的适当方法时发生


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

Data::isEven
是一个
谓词

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


因此,
isEven
是一个
谓词
,因为它接受
数据
,并返回
布尔值
,,就像其他人写的“Data::isEven”或“Data->Data.isEven()是这里的谓词一样。当我们调用这个谓词的test方法时,我们将数据实例(您有一个这样的实例流)作为参数传递到那里。

isEven()方法与谓词接口中的test()方法不匹配。我无法理解的是,编译器是如何监督这种不匹配的?其他答案会不断以高速更新。在某些时候,我的答案可能会在这样的更新中失去意义:-)每当您看到
ClassName::method
,第一个参数就会转换为方法调用的目标。谢谢您的解释很有帮助。我接受了答案。