Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Optional and orElse [duplicate]

Tags:

java

optional

I'm new to the Java optionals but I see this code written by another developer and I don't get it:

String t = null;
Optional.ofNullable("notnull")
    .orElse(
        Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))
    );

Why does this code throw the exception? Why does it even go to the "orElse" branch?

Is this because of some weird execution order? So the first optional's value is not set before the orElse branch is evaluated?

like image 511
breakline Avatar asked Aug 27 '19 12:08

breakline


2 Answers

The orElse stream is never invoked but the method itself is executed. This means that the method parameter is passed to it as well. So the part Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException")) is being called regardless of the value passed to the first Optional.ofNullable call.

If you don't want this to happen you will need to pass a Supplier like this:

String t = null;
Optional.ofNullable("notnull")
    .orElseGet(
        () -> Optional.ofNullable(t).orElseThrow(() -> new RuntimeException("MyException"))
    );

The supplier is only invoked when the orElseGet stream is invoked. Note that you'll need a RuntimeException instead of a checked exception in order to be able to break from the supplier.

like image 125
whitebrow Avatar answered Nov 03 '22 13:11

whitebrow


That's because the code inside orElse() will be always evaluated. In other words it will be executed even if you specify a non-empty Optional, so that's why the Exception will be thrown.

If you check the orElse() section of Java Optional – orElse() vs orElseGet() article, you can see that in their example, where it says:

We can easily infer that the parameter of orElse() is evaluated even when having a non-empty Optional.

like image 32
cнŝdk Avatar answered Nov 03 '22 13:11

cнŝdk