这是一个以谓词为参数的示例方法:
CloseWindow
我将上述函数称为:
void processFields(List<WebDataField> fields, Predicate<WebDataField> predicate) {
for (WebDataField webDataField : fields) {
boolean expectedCondition = predicate.test(webDataField);
}
}
另一个功能:
processFields(fields, w -> w.getFieldName().length() > 5);
在调用方,将这样调用doSomething()方法–
public void doSomething(Object someObject,Predicate<T> predicateInstance){
//doSomething method's code goes here
}
我检查了Java 8文档中的String / Integer / Object等,但没有发现实现doSomething(someObjectInstance, Integer i-> i>10)
接口的这些类中的任何一个。我不知道我在Java 8教程系列中错过了什么,但是我无法得到这种现象:
如果目标类型与Predicate类没有直接关系,编译器如何允许lambda表达式?
以上两种情况的答案都一样吗?
答案 0 :(得分:1)
lambda表达式(Integer i) -> i>1
的值不是Integer
,因此Integer
不必实现Predicate
就可以传递该lambda表达您的方法。
Integer
是lambda表达式的参数i
的类型。 (Integer i) -> i>1
可以表示具有单个方法的任何功能接口,该方法采用Integer
自变量并返回boolean
。因此,它适合Predicate<Integer>
功能界面。
您的其他lambda表达式-w -> w.getFieldName().length() > 5
-接受未指定类型的参数,并返回boolean
。为了使其能够通过编译,编译器必须将w
的类型推断为具有getFieldName()
方法的某个类或接口,该类或接口将返回具有length()
方法的某种类型的实例。当您将lambda表达式传递给需要processFields
的{{1}}方法时,编译器可以推断出lambda表达式的参数Predicate<WebDataField>
的类型为w
。>
答案 1 :(得分:1)
回答第一个问题:
上面的lambda表达式i-> i>10
是表达以下内容的较短方法:
Predicate<Integer> predicate = new Predicate<Integer>() {
@Override
public boolean test(Integer i) {
return i > 10;
}
};
随后将如下使用:
Integer someObjectInstance = 1;
doSomething(someObjectInstance, predicate);
因此目标类型(Integer
)具有“ 与谓词直接连接”。
继续第二个问题:
在Predicate<T>
上,T
是generic类型的参数。泛型类型参数仅接受引用类型,而不接受原始类型。因此,Predicate<T> p
始终必须具有类型为T
的对象实例作为参数(您称其为 someObjectInstance )。如果您想测试Integer
,请按照以下方式进行操作:
Integer someObjectInstance = 1;
doSomething(someObjectInstance, i-> i>10);
但是,如果您尝试使用原始类型整数(int
)调用该方法,则会出现语法错误:
int integer = 0;
worker.doSomething(integer, i -> i > 10); // The operator > is undefined for the argument type(s) Object, int
但是您可以通过显式提供泛型类型参数来帮助编译器。在这种情况下,它是Integer
,即int
的相应包装类型。这将因为autoboxing而起作用。
int integer = 0;
worker.<Integer> doSomething(integer, i -> i > 10);
但是您说的是“ 字符串/整数/对象等...没有找到实现谓词的所有此类”。对于原始类型,有专用的谓词接口。例如:IntPredicate
。
但是他们没有扩展接口Predicate<T>
。这是不可能的,因为IntPredicate extends Predicate<int>
之类的定义无效。如上所述,int
作为通用类型参数是不可接受的。
要使用IntPredicate
,可以声明一个方法
public <T> void doSomething(int i, IntPredicate intPredicate) {
// doSomething method's code goes here
}
并这样称呼它:
doSomething(integer, i -> i > 10);
要获得不同谓词接口的概述,请查看软件包java.util.function
reference。