Java: Lazy initialize a collection with Optional

In this short advice I would like to show you how to create null-safe code when working with unset data in a Java Bean or some API that you are using which may return a null reference. It will be an easy to read one liner.

The traditional way

In the early days of Java over twenty years ago the programming language was relatively easy to pick up when you had a background in C++. In C++ you have the concept of pointers which can for example point to an instance of a class.

The zero pointer in C++ is similar to the idea of building null into the Java language: This built-in literal can be assigned to variables to represent the fact that it has no destination and does not point to an instance of an object yet.

If you call a method of the type of a variable that holds null at this point a NullPointerException is raised. It is debatable whether it was a good idea to design the language this way (do a Internet search for “Null References: The Billion Dollar Mistake” for more information) but since it is there you have to check for unwanted null references before working with return values.

This leads to (ugly) code like the following:

SomeObject so = getSomeObject();
if (so == null)
  so = new SomeObject();
...
so.callX();

You call a certain method and assign the return value to a variable. In case the contract of the method contains null as a possible outcome the next code line contains an if statements checking for null and if that’s the case you either initialize the variable, raise an exception or do something else instead.

Alternatives

Instead of intentionally returning a null reference from your method you have – probably among others – two more options.

First, you can return an empty or dummy instance instead. This is not always sensible but in case your method should return a java.util.List with some data in it, most of the time it is perfectly fine to return an empty List instead.

For example you can lazy-initialize your List by adding the null check to your method that returns the List like so:

private List<String> someData;

public List<String> getSomeData() {
  if (Objects.isNull(this.someData))
    this.someData = new ArrayList<String>();
  return someData;
}

Second, you can work with Optional.empty() and return it. This way the one who calls your method has to think about the fact whether the expected data is really present. This brings us to a possible solution.

Make use of java.util.Optional

If you are working with Java Beans or an API that for some reason you can not change you can use the following idiom:

public List<String> getSomeData() {...}

Optional.ofNullable(getSomeData())
        .orElseGet(ArrayList::new);

If you then continue to work with that List for example by using the Java Streaming API the stream of elements simply is empty and just nothing will happen on that occasion. If the List is not null the Optional container will just return that list and the “orElseGet” method will not construct a new List.

By making use of java.util.Optional you can declutter your code and avoid checking for null references all the time even if its a valid return value in the contract of the API you are working with.