Reputation: 99
A method where I chain optionals does not behave how I thought it would from reading the docs.
Assume all function_n
return an Optional<Foo>
public Foo getFooFromService() {
return this.function_1()
.or(this.function_2())
.or(this.function_3())
.or(DEFAULT_VAL)
I thought that for the above code, if function_1
returned a non-absent Optional, then the program would return the inner value of it (the result of .get()) and not do any further computation on function_2
and function_3
My program is for sure doing that additional computation
Upvotes: 2
Views: 329
Reputation: 35457
Optional
So use Java's Optional
to write the rather legible code:
import java.util.*;
class Main {
public static void main(String[] args) {
new Main().getFooFromService();
}
String getFooFromService() {
return this.function_1()
.or(this::function_2) // Requires Java 9
.or(this::function_3) // Requires Java 9
.orElse("DEFAULT_VALUE");
}
Optional<String> function_1() {
System.out.println("function_1 called");
return Optional.empty();
}
Optional<String> function_2() {
System.out.println("function_2 called");
return Optional.of("b");
}
Optional<String> function_3() {
System.out.println("function_3 called");
return Optional.of("c");
}
}
You'll see that in this case, with the given setup, function_1
and function_2
are called, but not function_3
.
Upvotes: 2
Reputation: 49646
In order to return a value from getFooFromService
, function_1
and three or
s have to be executed, meaning that their parameters will be evaluated. function_2
and function_3
will be run under any circumstances.
The option that might be suitable for you is the overloaded version that takes a Supplier
which implies lazy evaluation.
public abstract T or(Supplier<? extends T> supplier)
UPDATE
It's a @Beta
method (a subject to change), and I find it entirely useless. It resolves a Supplier<? extend T>
to T
, thus ruins the opportunity of building a chain. Basically, you can't rewrite your snippet to use this method.
UPDATE 1
But you could switch to Java's Optional
and write
return function_1()
.orElseGet(() -> function_2()
.orElseGet(() -> function_3()
.orElse(DEFAULT_VAL)));
which isn't that expressive, but working as expected.
My formatting is awful, but you get the idea ;)
Upvotes: 5