Why and How to Use Optional in Java

The Optional object type in Java was introduced with version 8 of Java. It is used when we want to express that a value might not be known (yet) or it’s not applicable at this moment. Before Java 8 developers might have been tempted to return a null value in this case.

Ultimately, there are two scenarios for Optional:

  • Case 1: An empty box in which there is no value – Optional.empty().
  • Case 2: A box in which there is a value X – Optional.of(X).

Let’s have an example. What’s our car gas mileage?

  • Unknown / not applicable if we haven’t driven our car yet (Case 1).
  • 30 mpg if we have traveled 30 miles with 1 gallon (Case 2).

So how could we express this with a method and an Optional? Here is an example:

Optional<Integer> getMGP(int miles, int gallons) {
	if (miles == 0) {
		return Optional.empty();
	}
		return Optional.of(miles / gallons);
}

Next, if we want to use it:

System.out.println(getMGP(100, 3));
//prints Optional[33]
System.out.println(getMGP(0, 3));
//prints Optional.empty

As we’ve pointed, Optional is like a box, so to “unpack” this box and get the value inside, we have to use its get() method like this:

Optional<Integer> mpg = getMGP(100, 3);

if (mpg.isPresent()) {
	System.out.println(mpg.get()); // prints 33
} else {
	System.out.println("MPG is not available yet.");
}

Note that the isPresent() method is used before we try to get the mpg value. If we try get() on an empty Optional we’ll get java.util.NoSuchElementException:

Exception in thread "main" Optional.empty
java.util.NoSuchElementException: No value present
	at java.util.Optional.get(Optional.java:135)
	at testing.Test.main(Test.java:22)

To make our lives easier, Optional has a few additional methods:

  • ifPresent(Consumer c) – if the value is present, execute a consumer. With this we can rewrite the above if like this:
mpg.ifPresent(x -> System.out.println(x));
  • orElse(T other) – return a different value if there is no value. Note that if there is a value, it will be returned. For example, return 0 if there is no value:
mpg.orElse(0);
  • orElseGet(Supplier s) – if there is no value, then execute a supplier. For example, return 0:
mpg.orElseGet(() -> 0)
  • orElseThrow(Supplier s) – if there is no value, throw an exception, e.g. IllegalStateException:
mpg.orElseThrow(() -> new IllegalStateException())

That’s the beauty and power of Optional. As we know from the clean code paradigms, null values shouldn’t be returned so use Optional instead.

Comments

So empty here ... leave a comment!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Sidebar