我正在处理单行lambda和运行时异常。
我已经测试了以下用例,发现语句 1
未编译,而语句 2
可以正常编译。
new Thread(() -> throw new RuntimeException("test")); // 1
new Thread(() -> new RuntimeException("test")); //2
请帮助我理解为什么语句1不能编译而语句2可以正常编译。
答案 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
的单个表达式,但除此之外没有任何作用。
答案 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的答案。 欢迎进一步补充。