gpt4 book ai didi

java - 为什么 negate() 需要显式强制转换为 Predicate?

转载 作者:行者123 更新时间:2023-12-01 09:51:28 24 4
gpt4 key购买 nike

我有一个名单。在第 3 行,我不得不将 lambda 表达式的结果转换为 Predicate<String> .我正在阅读的书解释说,为了帮助编译器确定匹配的功能接口(interface)是什么,强制转换是必要的。

但是,我不需要在下一行进行这样的转换,因为我不调用 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

最佳答案

这不仅仅是因为您调用negate() .看看这个版本,它与你的非常接近,但可以编译:

Predicate<String> predicate = str -> str.length() <= 5;
names.removeIf(predicate.negate());

这个和你的版本有什么区别?这是关于 lambda 表达式如何获取它们的类型(“目标类型”)。

你认为这有什么作用?
(str -> str.length() <= 5).negate()?

您当前的答案是“它调用 negate() 上的 Predicate<String> 由表达式 str -> str.length() <= 5 给出”。对?但这只是因为这是您的本意。 编译器不知道 .为什么?因为它可以是任何东西。我自己对上述问题的回答可能是“它在我的其他功能接口(interface)类型上调用 negate...(是的,这个例子会有点奇怪)
interface SentenceExpression {
boolean checkGrammar();
default SentenceExpression negate() {
return ArtificialIntelligence.contradict(explainSentence());
};
}

我可以使用完全相同的 lambda 表达式 names.removeIf((str -> str.length() <= 5).negate());但意思是 str -> str.length() <= 5成为 SentenceExpression而不是 Predicate<String> .

解释: (str -> str.length() <= 5).negate()不做 str -> str.length() <= 5一个 Predicate<String> .这就是为什么我说它可以是任何东西,包括我上面的功能界面。

回到 Java... 这就是为什么 lambda 表达式具有“目标类型”概念的原因,它定义了编译器将 lambda 表达式理解为给定功能接口(interface)类型的机制(即,您如何帮助编译器了解表达式是 Predicate<String> 而不是 SentenceExpression 或其他任何可能的值)。您可能会发现通读 What is meant by lambda target type and target type context in Java? 很有用和 Java 8: Target typing

推断目标类型的上下文之一(如果您阅读了这些帖子上的答案)是调用上下文,其中您将 lambda 表达式作为函数接口(interface)类型的参数的参数传递,这适用于 names.removeIf(((str -> str.length() <= 5))); :它只是作为参数提供给采用 Predicate<String> 的方法的 lambda 表达式.这不适用于未编译的语句。

所以,换句话说...
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需要一个 Predicate<String> ,它肯定知道传递给方法的整个表达式必须是 Predicate<String> , 但它不会假设参数表达式中的任何 lambda 表达式都是 Predicate<String> (即使您通过调用 negate() 将其视为谓词;它可能是任何与 lambda 表达式兼容的东西)。

这就是为什么需要使用显式强制转换(或其他方式,如我给出的第一个反例)键入您的 lambda。

关于java - 为什么 negate() 需要显式强制转换为 Predicate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60348254/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com