内联Lambda语法引发异常

时间:2018-08-05 06:17:38

标签: java exception lambda

对于返回void的lambda,这是有效的:

Runnable b = () -> System.out.println("3");

但这不是:

Runnable b = () -> throw new RuntimeException("3");

我知道我可以将其放在大括号中,但是为什么这对于内联lambda无效?

1 个答案:

答案 0 :(得分:2)

() -> foo语法将lambda的主体定义为表达式(JLS 15.27.2),因此throw new RuntimeExpression("3")不会编译是完全合理的:这是一条语句,而不是表达式。因此,真正的问题是,为什么println会编译?毕竟,这也是声明。

JLS 15.27.3表示:

  

如果函数类型的结果为void,则lambda主体为语句表达式(第14.8节)或与void兼容的块。

您的示例都不是块(void兼容或其他),因此它们必须是语句表达式。这些定义在JLS 14.8中,包括:

StatementExpression:
  Assignment 
  PreIncrementExpression 
  PreDecrementExpression 
  PostIncrementExpression 
  PostDecrementExpression 
  MethodInvocation 
  ClassInstanceCreationExpression

请注意MethodInvocation-这就是让您的println lambda进行编译的原因。

因此,简而言之:第一个println之所以编译是因为它是语句表达式的MethodInvocation形式,而throw则不会编译,因为语句表达式不包含throw

请注意,所有语句表达式都是表达式(因此而得名),因此实际上可以归结为以下事实:尽管实际上我们只想到了println实际上是类型void的表达式。作为声明。 (实际上,我们通常将其视为语句的原因是,您只能将其用作语句表达式,如JLS 15.1中所述)。