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

在Java中(目前使用Java 8),我可以写这个,一切都会编译得很好:

Supplier<Long> asd = () -> {
    throw new RuntimeException();
};

然而,我不能这样写:

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

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

我的意思是,既然 lambda 只是抛出了 RuntimeException,为什么 JDK 不能将 lambda 表达式推断为:

new Supplier<Long>() {
    @Override
    public Long get() {
        throw new RuntimeException();
    }
};

这是否记录在规范/文档的某个地方?这是否仅在 JDK > 8 中添加?


答案 1

来自语言规范 JLS 15.27.2

lambda 主体可以是单个表达式,也可以是块 (§14.2)。

throw不是单个表达式(它是一个语句);所以你必须在一个块中使用它。


答案 2

您编写的是无效的 lambda。带括号和不带括号的表达式之间是有区别的。请参阅示例。以下表示返回。{}1L

Supplier<Long> asd = () -> 1L;

这相当于:

Supplier<Long> asd = () -> {
    return 1L;
}; 

但是,当您编写以下内容时:

Supplier<Long> asd = () -> throw new RuntimeException();

它将被翻译为无效的lambda:

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

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