【问题标题】:Why Consumer or Supplier argument needs {} for multiple annotations [duplicate]为什么 Consumer 或 Supplier 参数需要 {} 用于多个注释 [重复]
【发布时间】:2021-10-27 09:59:09
【问题描述】:

假设有一个Optional optString。现在,如果我按如下方式使用它:

optString.ifPresent({
    //some statements
    }, () -> throw new Exception());`, it fails to compile.

为什么我必须将throw new Exception() 包裹在花括号{} 内。

为什么我不能简单地做() -> throw new Exception

为什么编译器将thrownew 视为某些状态应该在一个块中?

在 IntelliJ 中失败并出现编译错误:expected ) expected { expected;Unexpected token

一个完整的例子:

class OptionalTest {

    Optional<String> testString() {
        return Optional.empty();
    }
    
    void getString() {
        var optStr = testString();
        optStr.ifPresentOrElse(s -> {
            
        }, () -> throw new RuntimeException());
    }
}

【问题讨论】:

  • 请发布完整示例
  • @SotiriosDelimanolis:恕我直言,标签optionaljava-8 非常重要,因为optional 通过适当的方法选择解决了问题,而java-8 是Java 的版本(可用的方法不同版本)。

标签: java lambda optional


【解决方案1】:

您不能像以前那样在 lambda 表达式中简单地 throw,因为 lambda 主体是单个表达式或块。 throw 是一个声明。

你必须将抛出异常包装到块中:

optStr.ifPresentOrElse(
    str -> /*do something*/,
    () -> { throw new RuntimeException(); });

还值得一提的是Optional#orElseThrow,它旨在实际抛出异常。传递给Supplier 的唯一参数是实例化异常的方式,如果Optional 为空,该方法只是接受它并抛出而不是你。

optStr.orElseThrow(() -> new RuntimeException());

【讨论】:

  • 那么optStr.ifPresent( /*do something*/).orElseThrow();的等价物是什么
  • @Mohammad 啊,我明白了你的问题。我已经相应地编辑了我的答案。
  • 旁注:当 Java 设计者在处理新的 switch 语法时,他们认为将 throw 语句括在大括号中太烦人了,所以他们添加了一个语法异常,所以你可以写,例如switch(someString) { case null -&gt; throw new RuntimeException("is null"); case String s -&gt; /* do something with s */ System.out.println(s); }。但我不知道有任何计划允许 lambda 表达式使用相同的方法。
  • @Holger:你有任何消息来源吗?我想了解更多。
  • 语法在the language specification;如您所见,有替代品SwitchRule: SwitchLabel -&gt; Expression ; SwitchLabel -&gt; Block SwitchLabel -&gt; ThrowStatement。我的示例使用了更新的语法,JDK 17 仅提供 preview feature
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
相关资源
最近更新 更多