用于引发异常的内联lambda语法



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

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

但这不是:

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

我知道我可以把它放在一个带大括号的块中,但为什么这不是内联lambda的有效语法呢?

() -> 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中所述(

最新更新