使用 Java 可选 ifPresentOrElse 方法时无法抛出 `checked` 异常

问题描述 投票:0回答:2

为什么使用

ifPresentOrElse
java 可选方法时,不能在 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 可选方法中抛出此类异常的原因是什么?

为什么我应该将我的异常设置为 RuntimeException 以使其正常工作,而它更应该被视为“自定义异常”而不是“运行时”?

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

其他研究除了确认这是不可能之外没有任何结果。

有什么想法吗?

java exception option-type java-9 java-11
2个回答
26
投票

您必须将投掷括在大括号内:

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

16
投票

当您想要指定两个非抛出操作时,方法

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

© www.soinside.com 2019 - 2024. All rights reserved.