如果lambda函数中有一个语句,我们可以省略为它定义完整的代码块:
new Thread(() -> System.out.println());
为什么抛出异常的语句不是这种情况?这会产生一个编译错误,说明'{' expected
:
new Thread(() -> throw new RuntimeException());
当然,将lambda主体包含在代码块中可以起作用:
new Thread(() -> {
throw new RuntimeException();
});
答案 0 :(得分:24)
AFAIK jls表示lambda body必须是:
表达式或块。它是这样的:
new Thread(() -> throw new RuntimeException());
既不是,编译器以某种方式通知你。
声明如下:
new Thread(() -> {
throw new RuntimeException();
});
使它成为一个块。以下是相关部分:
块是一系列语句,本地类声明和大括号内的局部变量声明语句。
答案 1 :(得分:20)
在Java8中,lambda body的语法只接受expression或block。鉴于throwing an exception是语句,而非表达式。
throwStatement: 'throw' expression ';' ;
lambdaBody: expression | block;
expression: lambdaExpression | assignmentExpression;
block : '{' blockStatements? '}' ;
如果需要,可以通过在下一个jdk版本中将throwStatement
包含到lambdaBody
中来增强它。实际上,正如你上面提到的,我们需要这样做例如:
lambdaBody: expression | block | throwStatement;
答案 2 :(得分:14)
throw
语句是一个语句,而不是表达式,所以它必须放在大括号内。根据{{3}},Java专家组当时对lambdas的语法进行了非正式调查,有四种选择:
#(arglist)(expr) and #(arglist){statements}
{ args -> statements }
(类似于Scala和Groovy)#{ args -> statements}
(args) -> { statements }
最终,选择是根据this article采用类似于C#的语法,就我所见,它看起来也与上面的最后一个选项最接近。在C#中,表达式lambdas 和语句lambdas 之间存在区别:
表达式lambda(C#):
(input parameters) => expression
声明lambda(C#):
(input parameters) => {statement;}
语法在this thread中解释。
在前一个主题中提到了在其他选项中选择此语法的基本原理:
选择此语法的决定是双重的:
语法在大多数主观测量中得分“相当不错”(尽管如此) 有这样的情况,它看起来很糟糕,就像所有其他人一样)。在 特别是,它适用于作为方法使用的“小”lambda 参数(一个常见的情况),也适用于大型 (多语句)lambdas。
尽管进行了广泛的搜索,但其中并没有明显的赢家 替代方案(每种形式都有一些好的方面,有些确实不是很好 好的方面,并没有明显优于 其他)。所以,我们觉得最好选择有的东西 已经证明在最喜欢的两种语言中效果很好 Java - C#和Scala - 而不是发明新东西。