Java lambda只抛出表达式而不是语句式

Tam*_*man 17 java lambda throw java-8 functional-interface

在Java(目前使用Java 8)中,我可以编写这个并且所有编译都很好:

Supplier<Long> asd = () -> {
    throw new RuntimeException();
};
Run Code Online (Sandbox Code Playgroud)

但是,我不能这样写:

Supplier<Long> asd = () -> throw new RuntimeException(); // This won't compile :(
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么Java的实现不允许这样的样式(表达式lambda)和只有语句/代码块样式lambda?

我的意思是,由于lambda 抛出RuntimeException,为什么JDK不能将lambda表达式推断为:

new Supplier<Long>() {
    @Override
    public Long get() {
        throw new RuntimeException();
    }
};
Run Code Online (Sandbox Code Playgroud)

这是在specs/docs中的某处记录的吗?这是仅在JDK> 8中添加的吗?

And*_*ner 23

从语言规范JLS 15.27.2:

lambda主体是单个表达式或块(第14.2节). 

throw不是单个表达式(它是一个声明); 所以你必须在一个区块中使用它.


Nik*_*las 18

你写的是一个无效的lambda.带括号{}和不带括号的表达式之间存在差异.查看示例.以下表示1L返回.

Supplier<Long> asd = () -> 1L;
Run Code Online (Sandbox Code Playgroud)

这相当于:

Supplier<Long> asd = () -> {
    return 1L;
}; 
Run Code Online (Sandbox Code Playgroud)

但是,当你写:

Supplier<Long> asd = () -> throw new RuntimeException();
Run Code Online (Sandbox Code Playgroud)

它将被翻译为无效的 lambda:

Supplier<Long> asd = () -> {
     return throw new RuntimeException();                    // invalid expression in Java
};
Run Code Online (Sandbox Code Playgroud)

简而言之,您可以理解() -> 1L为快捷方式{ return 1L; }.