gpt4 book ai didi

java - 为什么 Java 8 Stream forEach 方法的行为不同?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:04:43 25 4
gpt4 key购买 nike

根据我对 java 8 lambda 表达式的理解,如果我们不在花括号中的“->”之后包含代码,那么该值将被隐式返回。但在下面的示例中,forEach 方法需要 Consumer 并且表达式返回值,但编译器不会在 Eclipse 中给出错误。

List<StringBuilder> messages = Arrays.asList(new StringBuilder(), new StringBuilder());

messages.stream().forEach(s-> s.append("helloworld"));//works fine

messages.stream().forEach((StringBuilder s)-> s.append("helloworld")); //works fine

messages.stream().forEach(s-> s); // doesn't work , Void methods cannot return a value

messages.stream().forEach(s-> s.toString()); // works fine

messages.stream().forEach(s-> {return s.append("helloworld");}); // doesn't work , Void methods cannot return a value

messages.stream().forEach((StringBuilder s)-> {return s.append("helloworld");}); // doesn't work , Void methods cannot return a value

s.append 返回 StringBuilder 并且 s.toString() 返回 String 但 lambda 将其视为 无效

我在这里错过了什么?当我们在对象上调用方法时,为什么编译器不报错?

最佳答案

来自 JLS 15.27.3. Type of a Lambda Expression :

A lambda expression is congruent with a function type if all of the following are true:

  • The function type has no type parameters.

  • The number of lambda parameters is the same as the number of parameter types of the function type.

  • If the lambda expression is explicitly typed, its formal parameter types are the same as the parameter types of the function type.

    • If the lambda parameters are assumed to have the same types as the function type's parameter types, then:

    • If the function type's result is void, the lambda body is either a statement expression (§14.8) or a void-compatible block.

    • If the function type's result is a (non-void) type R, then either i) the lambda body is an expression that is compatible with R in an assignment context, or ii) the lambda body is a value-compatible block, and each result expression (§15.27.2) is compatible with R in an assignment context.

上面突出显示的句子意味着任何语句 lambda 表达式(即没有 block 的 lambda 表达式)匹配一个功能接口(interface),其单个方法的返回类型为 void(例如 Consumer forEach 方法所需的功能接口(interface))。

这解释了为什么 s.append("helloworld")s.toString()(您的 1,2 和 4 示例)作为语句 lambda 表达式可以正常工作。

示例 5 和 6 不起作用,因为它们具有 block lambda 主体,它们是值兼容的 lambda 表达式。要与 void 兼容,所有返回语句都必须不返回任何内容(即仅返回 return;)。

另一方面,以下 void-compatible block lambda 主体将通过编译:

messages.stream().forEach(s-> {s.append("helloworld");});
messages.stream().forEach(s-> {s.append("helloworld"); return;});

您的第 4 个示例 - messages.stream().forEach(s-> s); 不起作用,原因与以下方法未通过编译的原因相同:

void method (StringBuilder s)
{
s;
}

关于java - 为什么 Java 8 Stream forEach 方法的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38096582/

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