
Every serious Java developer or architect has heard about or experienced the nuisance of NullPointerException
exceptions.
What can you do? Often programmers use the null
reference to denote the absence of a value when they return values from methods, but that is a significant source of many problems.
To have good insight into the null
reference problem, consider reading Raoul-Gabriel Urma’s article, “Tired of Null Pointer Exceptions? Consider Using Java SE 8’s ‘Optional’!” That’ll bring you up to speed and introduce you to the Optional
class.
Let’s build on Urma’s work by seeing how to use Optional
the way it should be used. From the experience and hands-on point of view I gained when I was reviewing developers’ code, I realized developers are using the Optional
class in their day-to-day code. That led me to come up with these 12 best practices that will help you improve your skills—and avoid antipatterns.
This article and a follow-up article that will appear in Java Magazine soon will go through all the Optional
class methods released through Java 14. Since Java 15 is nearing completion, that will be covered too.
The origin of the Optional class
Java engineers have been working on the null
problem for a long time and they tried to ship a solution with Java 7, but that solution wasn’t added to the release. Let’s think back, though, and imagine the language designers’ thoughts about the Stream API. There is a logical return type (such as 0) to some methods such as count()
and sum()
when the value is absent. A zero makes sense there.
But what about the findFirst()
and findAny()
methods? It doesn’t make sense to return null
values if there aren’t any inputs. There should be a value type that represents the presence (or absence) of those inputs.
Therefore, in Java 8, a new type was added called Optional<T>
, which indicates the presence or absence of a value of type T
. Optional
was intended to be a return type and for use when it is combined with streams (or methods that return Optional
) to build fluent APIs. Additionally, it was intended to help developers deal with null
references properly.
By the way, here is how Optional
is described in the Java SE 11 documentation: “Optional
is primarily intended for use as a method return type where there is a clear need to represent ‘no result,’ and where using null
is likely to cause errors. A variable whose type is Optional
should never itself be null
; it should always point to an Optional
instance.”
My own definition, as you are going to see in my code recipes, is this: The Optional
class is a container type for a value that may be absent.
Moreover, several corner cases and temptations can be considered traps that could downgrade the quality of your code or even cause unexpected behaviors. I am going to show those in this series of articles.
You might now wonder, “Where is the code?” So, let’s jump in. My approach is to answer typical developer questions that categorize all the uses of the Optional
class. In this article, I will cover the following three big categories with 12 recipes:
- Why am I getting
null
even when I useOptional
? - What should I return or set when no value is present?
- How do I consume
Optional
values effectively?
In an upcoming article, I will cover two more categories:
- How do I avoid
Optional
antipatterns? - I like
Optional
; what can I do more professionally?
Why am I getting null even when I use Optional?
Usually, this question applies to the creation of an Optional
class and how to get the data.
Recipe 1: Never assign null to an optional variable. Sometimes when developers are dealing with a database to search for an employee, they design a method to return Optional<Employee>
. I have found developers still returning null
if no result is returned from the database, for example:
1 public Optional<Employee> getEmployee(int id) {
2 // perform a search for employee
3 Optional<Employee> employee = null; // in case no employee
4 return employee;
5 }
The code above is not correct, and you should avoid it completely. To correct it, you should replace line 3 with the following line, which initializes Optional
with an empty Optional
:
Optional<Employee> employee = Optional.empty();
Optional
is a container that may hold a value, and it is useless to initialize it with null
.