首页 > 解决方案 > 使用 Java 可选 ifPresentOrElse 方法时无法抛出“已检查”异常

问题描述

ifPresentOrElse为什么在使用java Optional 方法时不能在 orElse 部分中抛出已检查的异常?

例如:

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 以使其工作,而它更多地被视为“自定义异常”而不是“运行时”?

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

除了证实这是不可能的之外,其他研究没有任何结果。

任何想法 ?

标签: javaexceptionoptionaljava-9java-11

解决方案


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


推荐阅读