单行 Lambda 和 运行 时间异常 - 不编译?
Single line Lambda and Run-time exceptions - Not compiling?
我正在处理单行 lambda 和 运行 时间异常。
我测试了以下用例,发现语句 1
未编译 where as 语句 2
编译正常。
new Thread(() -> throw new RuntimeException("test")); // 1
new Thread(() -> new RuntimeException("test")); //2
请帮助我理解为什么语句 1 没有编译但语句 2 编译正常。
如果将第 1 行更改为:
,则会编译
new Thread(() -> { throw new RuntimeException("test"); });
大括号只能在单个语句中省略。
第二行是创建新 RuntimeException
的单个表达式,但除此之外没有其他效果。
我猜这是你想要的:
new Thread(() -> { throw new RuntimeException("test"); }); // 1
下面写成语句就好了:
new RuntimeException();
创建和抛出异常实例是不同的事情。因此,这没有任何用处;它只是让房间暖和了一点。
这正是您在第二种形式中所做的。
lambda 表达式定义(在 JLS 15.27. Lambda Expressions 中)为:
LambdaExpression:
LambdaParameters -> LambdaBody
LambdaBody 定义为:
LambdaBody:
Expression
Block
在你的两个 lambda 表达式中,你没有使用块作为 lambda 主体(这需要花括号),这意味着你必须使用表达式。
表达式定义为:
Expressions can be broadly categorized into one of the following syntactic forms:
Expression names (§6.5.6)
Primary expressions (§15.8 - §15.13)
Unary operator expressions (§15.14 - §15.16)
Binary operator expressions (§15.17 - §15.24, and §15.26)
Ternary operator expressions (§15.25)
Lambda expressions (§15.27)
new RuntimeException("test")
属于“主要表达式”类别,其中包括对象创建(创建的对象是 Exception
的事实没有区别)。因此它是一个有效的 lambda 主体。
另一方面,throw new RuntimeException("test")
不属于任何这些类别,因此不是表达式。
为了让 lambda 主体包含该语句,您必须使用 Block LambdaBody:
new Thread(() -> {throw new RuntimeException("test");});
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
接口一起使用,其 return 类型为 void
。实际上,它也可以与 returning 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");};
这是因为表达式 () -> new RuntimeException("test")
是 void-compatible 和 value-compatible(见 here)
A block lambda body is void-compatible if every return statement in the block has the form return;.
A block lambda body is value-compatible if it cannot complete normally
(§14.21) and every return statement in the block has the form return
Expression;.
这个答案的灵感来自@AndyTurner 和@Eran 的答案。
欢迎补充。
我正在处理单行 lambda 和 运行 时间异常。
我测试了以下用例,发现语句 1
未编译 where as 语句 2
编译正常。
new Thread(() -> throw new RuntimeException("test")); // 1
new Thread(() -> new RuntimeException("test")); //2
请帮助我理解为什么语句 1 没有编译但语句 2 编译正常。
如果将第 1 行更改为:
,则会编译new Thread(() -> { throw new RuntimeException("test"); });
大括号只能在单个语句中省略。
第二行是创建新 RuntimeException
的单个表达式,但除此之外没有其他效果。
我猜这是你想要的:
new Thread(() -> { throw new RuntimeException("test"); }); // 1
下面写成语句就好了:
new RuntimeException();
创建和抛出异常实例是不同的事情。因此,这没有任何用处;它只是让房间暖和了一点。
这正是您在第二种形式中所做的。
lambda 表达式定义(在 JLS 15.27. Lambda Expressions 中)为:
LambdaExpression:
LambdaParameters -> LambdaBody
LambdaBody 定义为:
LambdaBody:
Expression
Block
在你的两个 lambda 表达式中,你没有使用块作为 lambda 主体(这需要花括号),这意味着你必须使用表达式。
表达式定义为:
Expressions can be broadly categorized into one of the following syntactic forms:
Expression names (§6.5.6)
Primary expressions (§15.8 - §15.13)
Unary operator expressions (§15.14 - §15.16)
Binary operator expressions (§15.17 - §15.24, and §15.26)
Ternary operator expressions (§15.25)
Lambda expressions (§15.27)
new RuntimeException("test")
属于“主要表达式”类别,其中包括对象创建(创建的对象是 Exception
的事实没有区别)。因此它是一个有效的 lambda 主体。
另一方面,throw new RuntimeException("test")
不属于任何这些类别,因此不是表达式。
为了让 lambda 主体包含该语句,您必须使用 Block LambdaBody:
new Thread(() -> {throw new RuntimeException("test");});
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
接口一起使用,其 return 类型为 void
。实际上,它也可以与 returning 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");};
这是因为表达式 () -> new RuntimeException("test")
是 void-compatible 和 value-compatible(见 here)
A block lambda body is void-compatible if every return statement in the block has the form return;.
A block lambda body is value-compatible if it cannot complete normally (§14.21) and every return statement in the block has the form return Expression;.
这个答案的灵感来自@AndyTurner 和@Eran 的答案。 欢迎补充。