为什么必须把一个完整的代码块放在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版本中包含throwStatementlambdaBody来增强它。 事实上,我们需要如上所述。 例如:

 lambdaBody: expression | block | throwStatement;