【问题标题】:Java lambda only throwing expression-style instead of statement-style [duplicate]Java lambda仅抛出表达式样式而不是语句样式[重复]
【发布时间】:2019-05-02 14:58:42
【问题描述】:

在 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中添加的吗?

【问题讨论】:

  • 如果我没记错的话,你的声明 throw new RuntimeException() 周围的 {} 是一个“匿名函数”。我的猜测是开发人员决定所有调用都应该在一个方法中,而不是在你要求的风格中。这绝不是权威,因此是评论,而不是答案......
  • 您不能使用表达式语法,因为throw 语句不是表达式。就这么简单。
  • 因为 throw 不是一个表达式,就像 return 不是一个表达式一样?
  • 注意:C# got throw expressions in version 7。为 Java 提出这样的特性可能是一个好主意(尤其是如果 Java 有一个空合并运算符,因为这似乎是 C# 中 throw 表达式的主要用例)。

标签: java lambda java-8 throw functional-interface


【解决方案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();
    

    它会被翻译成 invalid lambda:

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

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

    【讨论】:

    • 情况并非完全如此,因为以下程序是有效的:Consumer&lt;String&gt; consumer = str -&gt; System.out.println(str)。这没有详细说明Consumer&lt;String&gt; consumer = str -&gt; { return System.out.println(str); }(这同样是一个无效程序)。添加了一些特殊规则以适应void 类型的表达式;只是没有添加这些相同的规则来适应 throw 语句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    相关资源
    最近更新 更多