Java 8: Removing null checks with Optional
If-statements are all around us and a big amount of them are simply checking if a value is there or not.
If we now for a minute move away from this imperative way of thinking - why should we have to explicitly explain how to do a null check? Why can't we just let Java take care of the how so we can focus on the what?
That's exactly what
Optional can do for us.
Optional is a container object that may or may not contain a non-null value.
To interact with the value,
Optional offers a set of useful methods that abstract away the null checks.
This leaves us with more concise and declarative code that is focused on the details we care about.
Let's start coding
To get familiar with how to interact with
Optional, consider the following.
We have a method -
getRelevantArticleFor - that finds an article that is relevant for a given tag.
Optional<Article> article = getRelevantArticleFor("Java");
This method returns an
Optional<Article> that may or may not contain an article depending on if a relevant article was found.
Now we want to be able to use this article, and to do so we're going to use
Let’s start with a classic. If a relevant article was found - do some work.
Instead of using an if-statement to check if not null, we'll use
article.ifPresent(a -> print(a));
ifPresent is a higher-order function that takes a consumer function that describes what we want done if the value is present.
Moving on - let's look at a few options for fetching the actual article out from
First of all,
Optional has a
The problem with
get, is that it'll throw an exception if
Optional is empty.
So, what else can we do?
orElse is another function for fetching the article, where you're given the chance to provide an alternative value.
But, why fetch the alternative article before we’re sure we need it?
Instead, we could use a second option -
orElseGet - which takes a supplier that is executed if
Optional is empty.
article.orElseGet(() -> getNewestArticle());
Now that we've looked at functions that simply act based on the existence or non existence of
Optional's value, let's move to functions that changes value inside
If we have some requirements that the value needs to fulfill - say the relevant article must be less than a month old - we can use
filter to check the value against a predicate.
article.filter(a -> newerThanAMonth(a));
If the value fails the predicate, it'll return an empty
filter returns an
Optional, we can combine it with other functions in
As an example, let’s combine
orElseGet to find a relevant article the last month, and if not found, return the newest article we got.
article.filter(a -> newerThanAMonth(a)) .orElseGet(() -> getNewestArticle());
Optional also offers the
map function, allowing us to transform the value.
An example of this could be transforming an
Optional containing a potential article to an
Optional containing a potential title.
Optional's API also contain
flatMap could be useful if objects wrapped by
Optional also contains
To reason about this, let's say that our article has an
Optional<Date>, holding the date when published. If the article yet hasn't been published, the
Optional would be empty.
If we use the
map function, we'll end up with a nested
Optional<Optional<Date>> published = article.map(Article::published);
This is not an ideal solution. So instead we could use
flatMap to flatten the result.
Optional<Date> date = article.flatMap(Article::published);
A word of caution
Hopefully this post gives you some ideas about how you could use
Optional in your code.
However, it's worth noting that
Optional has become a touchy subject in the Java environment and it's a lot of opinions about where and when to use it. This is however outside the scope of this post. So for further reading, I recommend checking out The Design of Optional by Nicolai Parlog.