为什么必须把一个完整的代码块放在lambda体中呢?
如果在lambda函数中有一个单独的语句,我们可以省略为它定义完整的代码块:
new Thread(() -> System.out.println());
为什么不是那种抛出exception的语句呢? 这产生了编译错误,指出'{' expected
:
new Thread(() -> throw new RuntimeException());
当然,在一个代码块中封装lambda体是可行的:
new Thread(() -> { throw new RuntimeException(); });
一个throw
语句就是一个语句,而不是一个expression式,所以它必须放在大括号内。 根据这篇文章 ,Java专家组对当时的lambdaexpression式进行了非正式的调查,有四个选项:
- Strawman :
#(arglist)(expr) and #(arglist){statements}
- BGGA :
{ args -> statements }
(类似于Scala和Groovy) - SotL :
#{ args -> statements}
- 雷蒙德 :(
(args) -> { statements }
最终,根据这个线程的select是采用类似于C#的语法,就我所见,它也看起来最接近上面的最后一个选项。 在C#中, expression式lambdas和语句lambdas之间有一个区别:
expression式lambda(C#):
(input parameters) => expression
语句lambda(C#):
(input parameters) => {statement;}
该语法在此MSDN文档页面中进行了解释。
在上一个线程中提到了select其他选项的基本原理:
select这种语法的决定是双重的:
在大多数主观测量中,语法得分“相当不错”(虽然有些情况看起来很糟糕,就像所有其他人一样)。 特别是,它适用于作为方法论点的“小”lambdaexpression式(一种常见的情况),也适用于大型(多语句)lambdaexpression式。
尽pipe大量的search,但是替代scheme中没有明显的赢家(每个表格都有一些好的方面,有些方面并不是很好,没有哪个表格比其他表格更好)。 所以,我们觉得select一些已经certificate在Java – C#和Scala这两种语言中运行良好的东西会更好一些,而不是发明一些新东西。
AFAIK JLS说,拉姆达体必须是:
expression式或块 。 像这样:
new Thread(() -> throw new RuntimeException());
既不是,编译器以某种方式通知你。
声明如下:
new Thread(() -> { throw new RuntimeException(); });
使它成为一个块。 这里是相关部分:
块是大括号内的一系列语句,局部类声明和局部variables声明语句 。
在Java8中, lambda体的语法只接受expression式或块 。 抛出一个exception是一个语句 ,而不是一个expression式 。
throwStatement: 'throw' expression ';' ; lambdaBody: expression | block; expression: lambdaExpression | assignmentExpression; block : '{' blockStatements? '}' ;
如果需要,可以通过在下一个jdk版本中包含throwStatement
到lambdaBody
来增强它。 事实上,我们需要如上所述。 例如:
lambdaBody: expression | block | throwStatement;