K M*_*Man 7 java lambda predicate
我有一个名字列表。在第 3 行,我必须将 lambda 表达式的结果转换为Predicate<String>. 我正在阅读的书解释说,为了帮助编译器确定匹配的功能接口是什么,强制转换是必要的。
但是,我不需要在下一行进行这样的演员表,因为我不调用negate(). 这有何不同?我知道negate()这里返回了Predicate<String>,但是前面的 lambda 表达式不一样吗?
List<String> names = new ArrayList<>();
//add various names here
names.removeIf(((Predicate<String>) str -> str.length() <= 5).negate()); //cast required
names.removeIf(((str -> str.length() <= 5))); //compiles without cast
Run Code Online (Sandbox Code Playgroud)
这并不完全是因为您调用了negate()。看看这个版本,它与你的非常接近,但确实可以编译:
Predicate<String> predicate = str -> str.length() <= 5;
names.removeIf(predicate.negate());
Run Code Online (Sandbox Code Playgroud)
这个和你的版本有什么区别?它是关于 lambda 表达式如何获得它们的类型(“目标类型”)。
你觉得这有什么作用?
(str -> str.length() <= 5).negate()?
Run Code Online (Sandbox Code Playgroud)
您当前的回答是,“它要求negate()对Predicate<String>由下式给出str -> str.length() <= 5”。对?但这只是因为这是你的意思。编译器不知道。为什么?因为它可以是任何东西。我自己对上述问题的回答可能是“它调用negate了我的其他功能接口类型......(是的,这个例子会有点奇怪)
interface SentenceExpression {
boolean checkGrammar();
default SentenceExpression negate() {
return ArtificialIntelligence.contradict(explainSentence());
};
}
Run Code Online (Sandbox Code Playgroud)
我可以使用完全相同的 lambda 表达式,names.removeIf((str -> str.length() <= 5).negate());但意思 str -> str.length() <= 5是 aSentenceExpression而不是 a Predicate<String>。
说明:(str -> str.length() <= 5).negate()不会使str -> str.length() <= 5一个Predicate<String>。这就是为什么我说它可以是任何东西,包括我上面的功能界面。
回到 Java... 这就是为什么 lambda 表达式有“目标类型”的概念,它定义了编译器将 lambda 表达式理解为给定功能接口类型的机制(即,您如何帮助编译器知道表达式是一个Predicate<String>而不是SentenceExpression它可能是其他任何东西)。您可能会发现阅读Java 中 lambda 目标类型和目标类型上下文的含义是什么很有用?和Java 8:目标类型
推断目标类型的上下文之一(如果您阅读了这些帖子的答案)是调用上下文,您可以在其中传递 lambda 表达式作为函数接口类型的参数的参数,这适用于names.removeIf(((str -> str.length() <= 5)));:它只是作为参数提供给采用Predicate<String>. 这不适用于未编译的语句。
所以,换句话说……
names.removeIf(str -> str.length() <= 5);在参数类型明确定义期望的 lambda 表达式类型的地方使用 lambda 表达式(即,目标类型str -> str.length() <= 5明确为Predicate<String>)。
然而,(str -> str.length() <= 5).negate()它不是一个 lambda 表达式,它只是一个碰巧使用 lambda 表达式的表达式。这就是说,str -> str.length() <= 5在这种情况下,不在确定 lambda 表达式的目标类型的调用上下文中(如上一条语句的情况)。是的,编译器知道removeIf需要 a Predicate<String>,并且它肯定知道传递给方法的整个表达式必须是 a Predicate<String>,但它不会假设参数表达式中的任何 lambda 表达式都是 a Predicate<String>(即使你对待它通过调用negate()它作为谓词;它可以是任何与 lambda 表达式兼容的东西)。
这就是为什么需要使用显式强制转换(或其他方式,如我给出的第一个反例)来输入 lambda 的原因。
| 归档时间: |
|
| 查看次数: |
246 次 |
| 最近记录: |