为什么 Consumer 或 Supplier 参数需要 {} 用于多个注释

Why Consumer or Supplier argument needs {} for multiple annotations

假设有一个 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());
    }
}

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

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

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

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

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