12 recipes for using the Optional class as it’s meant to be used

By 31 de julio de 2020Ciberseguridad

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 TOptional 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 use Optional?
  • 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.

Leave a Reply

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.