【问题标题】:Unable to throw a `checked` exception when using Java Optional ifPresentOrElse method使用 Java 可选 ifPresentOrElse 方法时无法抛出“已检查”异常
【发布时间】:2020-11-06 16:50:50
【问题描述】:

为什么在使用ifPresentOrElsejava可选方法时,orElse部分不能抛出checked Exception?

例如:

dao.findBook(id).ifPresentOrElse(book -> {
    printingService.print(book, printerName);
    changeBookPrintDate(book.getId(), LocalDateTime.now());
}, () -> new BookNotFoundException());

其中BookNotFoundException 是扩展Exception 类的自定义异常(检查异常)。

但是这段代码让编译器不爽:

unreported exception com...exception.BookNotFoundException; must be caught or declared to be thrown

(知道它已经在方法声明中抛出,并且用try catch包围这个块并不能解决编译问题。

但如果我们将BookNotFoundException 扩展为RuntimeException(未选中),那么一切都会完美运行。

有人知道为什么吗?

在这个 java 9 Optional 方法中阻止抛出此类异常的原因是什么?

为什么我应该将我的异常设置为 RuntimeException 以使其工作,而它更多地被视为 'custom exception' 而不是 'runtime' ?

这个question 正在解决同样的问题,但对于 java 8 lambdas,所以我不知道这是否同样适用于 java 9 Optionals。

除了确认 it is not possible 之外,其他 researches 无处可寻。

有什么想法吗?

【问题讨论】:

    标签: java exception optional java-9 java-11


    【解决方案1】:

    方法ifPresentOrElse是一个有用的工具,当你想指定两个非抛出动作时,你可以在任何一种情况下在方法调用之后继续。但是当你想在缺少值的情况下抛出时,这是一个不必要的复杂化。只需使用

    var book = dao.findBook(id).orElseThrow(BookNotFoundException::new);
    printingService.print(book, printerName);
    changeBookPrintDate(book.getId(), LocalDateTime.now());
    

    由于此构造将抛出不存在的值,因此代码流将仅针对当前值继续。所以你可以在后续代码中像普通的局部变量一样使用book,但要保证永远不会是null

    方法orElseThrow 需要一个Supplier 来抛出异常,而不是抛出一个函数。这样,供应商可以构造一个检查异常而不抛出它,orElseThrow 的通用签名声明抛出供应商产生的任何类型。

    public <X extends Throwable> T orElseThrow​(Supplier<? extends X> exceptionSupplier) throws X

    【讨论】:

    • 感谢您的回答,是的,我可以按照您所说的那样使用 orElseThrow,但我的问题完全在 java-9 ifPresentOrElse 上,它适用于缺少值的情况下的未检查异常,但不适用于检查那些。所以只是为了了解为什么以及是否在 java9 Optionals 中提供了替代方案。谢谢
    • 技术原因是你传递了一个Runnable 并且它的run() 方法没有声明任何检查异常,因此你不能抛出检查异常。答案中已经给出了使用不支持检查异常的Runnable 的语义原因;这不是预期的用例。答案中也已经给出了替代方案,即使用它的预期方式。
    【解决方案2】:

    你必须用方括号添加 throw:

    *() -> { throw new BookNotFoundException(); }*
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      相关资源
      最近更新 更多