何时大括号在Java 8 lambda语法中是可选的?

我意识到Java 8 lambda实现可能会发生变化,但在lambda build b39中,我发现只有当lambda表达式返回非void类型时才能省略大括号。 例如,这编译:

public class Collections8 { public static void main(String[] args) { Iterable names = Arrays.asList("Alice", "Bob", "Charlie"); names.filter(e -> e.length() > 4).forEach(e -> { System.out.println(e); }); } } 

但删除这样的大括号:

 names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); 

给出错误

 Collections8.java:6: error: method forEach in interface Iterable cannot be applied to given types; names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); ^ required: Block found: lambda reason: incompatible return type void in lambda expression where T is a type-variable: T extends Object declared in interface Iterable 

谁能解释一下这里发生了什么?

当lambda主体是单个表达式或void方法调用时,您可以省略大括号。 每个表达式都计算为一个值,因此不能为空。

如果lambda的主体是一个语句块(例如,一系列计算后跟一个return语句),或者lambda没有值(即具有void返回类型)并且不是单个void方法调用,则必须使用块forms,需要括号。

在块样式的lambda中,如果return值,则所有可能的代码路径必须return值或throw Throwable

这只是:EG(主要)决定语法。

在考虑了许多替代方案之后,我们决定基本上采用C#语法。 我们可能仍然会进一步考虑细节(例如,细箭头与胖箭头,特殊的nilaryforms等),并且还没有就方法参考语法做出决定。

C#语法是:

 lambda = ArgList Arrow Body ArgList = Identifier | "(" Identifier [ "," Identifier ]* ")" | "(" Type Identifier [ "," Type Identifier ]* ")" Body = Expression | "{" [ Statement ";" ]+ "}" 

表达式求值为某事,您不能在Java中使用void表达式。 这是一个声明,因此你需要围绕它。

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html

我已经尝试过您的代码,并且对于最新的JRE版本,我认为它会没问题。

以下是我从Oracle Java文档中引用的内容。

在lambda表达式中,必须将语句括在大括号( {} )中。 但是,您不必在大括号中包含void方法调用。
例如,以下是有效的lambda表达式:

 email -> System.out.println(email) 

该文件非常清楚地解释了。 希望这可以解决您的问题。

参考文献: https : //docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

如果没有大括号,lambda会自动返回 – >运算符后面的一个表达式。
因此,当你有一个什么都不返回的lambda时,你必须使用大括号