post-photo

Java8 orElse versus orElseGet – easily misused

So, the Java8 Optional has two really cool (and similar) functions: the orElse() and the orElseGet().

text

If we quickly read the javadoc for each, we will only see a small difference;

Why can they be easily misused? What’s the difference? Let’s write some code! (Or use this if you are lazy!)

private static String functionWithSideEffect() {
    System.out.println("Yes this is a sideffect!");
    return "And this is the returned value!";
}
Optional<String> empty = Optional.empty();
Optional<String> something = Optional.of("something");
String a = empty.orElse(functionWithSideEffect());
String b = something.orElse(functionWithSideEffect());
String c = empty.orElseGet(()->functionWithSideEffect());
String d = something.orElseGet(()->functionWithSideEffect());

So, the code is simple, after the run we will see;

But what happened on the console? How many side effects did we get? 3! Why 3? That’s the million dollar question, that is, if you are writing code while you are half asleep, or before your first coffee. We need to go back to the basics.

x = a(b(c(1+1)))
----------------
val1 = 1+1
val2 = c(val1)
val3 = b(val2)
x = a(val3)

The code above the line will be something like the code under the line when we compile it. If we apply this logic to the orElse, we will get something like this:

String b = something.orElse(functionWithSideEffect());
---------------
String val1 = functionWithSideEffect();
String b = something.orElse(val1);

Sooo that’s why we have 3 side effects instead of 2.

If we read the javadoc again, we can see that the difference is bigger then we first thought. It says “other – the value to be returned if there is no value present, may be null” the VALUE.

What is confusing about this name? Why would a programmer ever misuse this? If you read something like “else,” you will associate something like:

if(condition){
  return func1();
} else {
  return func2();
}
OR
condition ? func1() : func2();

But if we want to visualize the a.map(a ->func1(a)).orElse(func2()) – will get something like:

String val2 = func2();
if(a.isPresent()){
  return func1(a.get());
} else {
  return val2;
}

And why does the orElseGet have no side effects? Because it’s in the definition; “whose result is returned if no value is present”. It’s actually translated something like an if-else or ?: .

An interesting point of view is; we must minimize the functions with side effects in our codebase (like functional programming does), and we will fall harder into making mistakes like this. Additionally, it would be an interesting language/editor feature if we could tag the functions with side effects, and the IDE or the compiler would warn us when we do questionable things like writing a function to an “always will run” spot. Or if the VM optimized itself to not calculate never read variables (but it would cause other strange effects…).

If our function has no side effect its return value will be calculated, and dropped, but it will not cause any trouble (at least if it’s not calculated too slow). So basically the orElse can be used if you use only pure functional functions, but you could still have some unwanted behavior because of the unnecessary calculation time.

I think a much better naming could be orElse -> orElseConstant and orElseGet -> orElse.

So that’s why we should use orElseGet and not the orElse (or read carefully the javadoc at any hour)!

Wanari is a custom software development company, founded in 2000. You just read a post on our tech blog.

Our core technologies are Modern Java and Scala, plus we also build native mobile applications. If you enjoyed this post, you should follow us on LinkedIn or Instagram and get notified when we share more.

Got feedback? Leave a comment or write us an email: hello@wanari.com

member photo

His precision is only coupled by his attention to detail. (Really.) He is passionate about becoming more and more effective in software development and loves experimenting with new technologies.

Latest post by Gergő Törcsvári

Learning by Doing – BlockChain & Akka Tutorial