单行Lambda和运行时异常-不编译?

时间:2018-08-01 05:30:05

标签: java lambda runtimeexception

我正在处理单行lambda和运行时异常。

我已经测试了以下用例,发现语句 1 未编译,而语句 2 可以正常编译。

 new Thread(() -> throw new RuntimeException("test")); // 1
 new Thread(() -> new RuntimeException("test")); //2

请帮助我理解为什么语句1不能编译而语句2可以正常编译。

5 个答案:

答案 0 :(得分:6)

lambda表达式在JLS 15.27. Lambda Expressions 中定义为:

  

LambdaExpression
     LambdaParameters-> LambdaBody

LambdaBody定义为:

  

LambdaBody
  表情
  阻止

在两个lambda表达式中,您都不使用块作为lambda主体(这需要花括号),这意味着您必须使用Expression。

表达式定义为:

  

表达可以大致分为以下一种语法形式:

     
      
  • 表达式名称(第6.5.6节)

  •   
  • 主表达式(§15.8-§15.13)

  •   
  • 一元运算符表达式(§15.14-§15.16)

  •   
  • 二进制运算符表达式(§15.17-§15.24和§15.26)

  •   
  • 三元运算符表达式(§15.25)

  •   
  • Lambda表达式(§15.27)

  •   

new RuntimeException("test")属于“主表达式”类别,其中包括对象的创建(创建的对象是Exception的事实没有区别)。因此,这是一个有效的lambda主体。

另一方面,throw new RuntimeException("test")不属于这些类别,因此不是表达式。

要使lambda主体包含该语句,必须使用Block LambdaBody:

new Thread(() -> {throw new RuntimeException("test");});

答案 1 :(得分:3)

如果将行号1更改为以下行,则会进行编译:

new Thread(() -> { throw new RuntimeException("test"); });

仅可对单个语句省略大括号。

第二行是创建新RuntimeException的单个表达式,但除此之外没有任何作用。

请参见Java Lambda Expressions Syntax Specification

答案 2 :(得分:2)

可以将以下内容写为语句:

new RuntimeException();

创建和引发异常实例是分开的事情。因此,这无济于事。只是让房间变热了。

这正是您在第二种形式中所做的。

答案 3 :(得分:0)

我猜这就是你想要的:

new Thread(() -> { throw new RuntimeException("test"); }); // 1

答案 4 :(得分:0)

lambda表达式的基本语法为:

(parameters) -> expression

(parameters) -> {statements;}

在您的第一个语句中,throw new RuntimeException("test");是一个声明(更具体地说,是一个throw Statement),因此应该用方括号括起来:

new Thread(() -> {throw new RuntimeException("test")}); 

在第二条语句中,new RuntimeException("test")表达式(更具体地说,是Class Instance Creation Expression)。这就是为什么不用括号和分号就可以使用它的原因。

================一些额外的东西===================

在这里,lambda表达式() -> new RuntimeException("test")与返回类型为Runnable的{​​{1}}接口一起使用。实际上,它也可以用于返回void的内容,例如:

Exception

在这种情况下,相同的表达式被评估为

  @FunctionalInterface interface ExceptionSupplier{Exception supply();} //another functional interface that it works with!

  ExceptionSupplier e = () -> new RuntimeException("test");
  System.out.println(e.supply()); //prints "java.lang.RuntimeException: test"

这是因为表达式ExceptionSupplier e = () -> {return new RuntimeException("Test");}; void兼容的值兼容的(请参见here

  

如果该块中的每个return语句都具有return;形式,则该块lambda主体为 void兼容

     

如果不能正常完成,则lambda主体是值兼容的   (第14.21节),并且该块中的每个return语句的格式均为return   表情;

此答案的灵感来自@AndyTurner和@Eran的答案。 欢迎进一步补充。