简体   繁体   中英

Unable to throw a `checked` exception when using Java Optional ifPresentOrElse method

Why a checked Exception can't be thrown in the orElse part when using ifPresentOrElse java Optional method?

For example:

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

where BookNotFoundException is a custom exception extending Exception class (checked exception).

but this code makes the compiler upset:

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

(knowing that it is already thrown in the method declaration, and surrounding this block with try catch doesn't resolve the compilation problem).

But if we make BookNotFoundException to be extending RuntimeException (which is unchecked), then all works perfectly.

Anyone knows why?

What's the reason that prevents throwing such kind of exceptions in this java 9 Optional method?

And why should I make my exception a RuntimeException to make it works while it is more to be considered a ' custom exception ' more than it is ' runtime '?

This question is addressing the same problem but for java 8 lambdas, so I don't know if the same applies for java 9 Optionals.

Other researches leaded nowhere other than confirming that it is not possible .

Any Idea?

The method ifPresentOrElse is a useful tool when you want to specify two non-throwing actions, so that you can continue after the method invocation in either case. But when you want to throw in the case of absent values, it's an unnecessary complication. Just use

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

Since this construct will throw for an absent value, the code flow will only continue for present values. So you can use book in the follow-up code like an ordinary local variable, but with the guaranty that it will never be null .

The method orElseThrow expects a Supplier for the exception to be thrown, instead of a function that throws. That way, the supplier can construct a checked exception without throwing it and the generic signature of orElseThrow declares to throw whatever type the supplier produced.

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

You must add the throw with square brackets:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM