Optional in Java
Optional<T>
is a new class introduced in Java 8. However, a very similar class has been available in Guava for quite some time.
Optional
is a generic class which should be used to represent the concept that a value might be missing. Very often methods that might return a valid object only under some conditions end up returning null
in case no valid object could be built. For instance, Map::get
returns null
in case the key could not be found in the map. This tends to lead to errors such as NullPointerException
; also, quite often, when you end up with a null
reference it’s hard to track down where it came from.
What’s Optional good for? Link to heading
An Optional
is designed to avoid NullPointerException
: calling a method that returns some kind of object can always hide the fact that the method returns null
. However, if the method returns Optional
, the caller cannot ignore this fact and has to perform some explicit check to detect the case where the Optional
is not available. This is good also from an API design point of view: the return value of the object already describes the fact that the result might not be present. So, Optional
makes both the intent of the author clearer and helps avoid bugs. A win-win!
How can you create an Optional? Link to heading
Let’s first take a look at how Optional
is created. For Java 8’s version, we can create it using one of these three methods:
Optional.of(what); // Requires that what is not null
Optional.empty(); // Means a missing optional
Optional.ofNullable(what); // what can be null or not null
For Guava’s version, we can use:
Optional.of(what); // Requires that what is not null
Optional.absent(); // Means a missing optional
Optional.fromNullable(what); // what can be null or not null
Generally we’d want to use of
or empty
/absent
; however sometimes it’s useful to use ofNullable
/fromNullable
to wrap a non-optional-aware method such as Map::get
.
How is an Optional used? Link to heading
You can use an Optional
like this:
Optional<String> myOptional = getAStringMaybe();
if (myOptional.isPresent()) {
doSomethingWith(myOptional.get());
} else {
handleCaseMyOptionalIsNull();
}
With Java 8, you can also do things such as:
Optional<T> myOptional = getMyOptional();
myOptional.ifPresent(t -> doSometingWith(t));
Optional<V> otherOptional = myOptional.map(t -> convertToV(t));
Note that calling get
with a missing optional raises a NoSuchElementException
for Java 8’s version, and IllegalStateException
for Guava.
Both API have methods orElse
/or
to return a “default value” in case the optional is absent.