Understanding Java Optional
By: Anurag Sharma
Tags: Optionals, Java, Clean Code, Design Patterns, Programming

Photo by Arnel Hasanovic on Unsplash

Optional introduced in Java in version 8 is often misused. Eliminating nulls isn’t a goal of Optional.

The primary design goal for Optional is to be used as the library method return value of functions when a return value might be absent. The intent is that the caller immediately checks the Optional and extract the actual value if it is present. If the value is absent, the caller can substitute a default value, throw an exception, or apply some other policy. This is typically done by chaining fluent method calls off the end of a stream pipeline (or other methods) that return Optional values.

Let us discuss where not to use optional:

Places Not to Use Optional

Avoid using Optional in method parameters

With an Optional parameter, you go from having 2 possible inputs: null and not-null, to three: null, non-null-without-value, and non-null-with-value. Add to that the fact that overloading has long been available to convey that some parameters are optional, and there's really no reason to have Optional parameters. Code analysis tools such as SonarQube and IntelliJ flag Optional in method parameters as a major code smell(RSPEC-3553).

Since the main point of Optional is to provide a means for a function returning a value to indicate the absence of a return value. See this discussion. This allows the caller to continue a chain of fluent method calls.

Passing an optional argument to a method, this could be made to work, but it’s rather clumsy. Suppose you have a method that takes a string followed by an optional second string. Accepting an Optional as the second arg would result in code like this:

foo("bar", Optional.of("baz"));

foo("bar", Optional.empty());

Even accepting null is nicer:

foo("bar", "baz");

foo("bar", null);

Probably the best is to have an overloaded method that accepts a single string argument and provides a default for the second:

foo("bar", "baz");

foo("bar");

This does have limitations, but it’s much nicer than either of the above.

Avoid using Optional in fields

Java Optional is also not recommended to be used as fields in POJOs. Java Optional is not serializable and if you really have a requirement of the optional field you can use nullable fields with getter returning Optional.

Avoid using Optional in collections

Sometimes people want to put Optional into collections, like List<Optional<X>> or Map<Key,Optional<Value>> . This too is usually a bad idea. This may seem required to distinguish between the absence of the record and null record. It's often better to replace these usages of Optional with Null-Object values (not actual null references), or simply to omit these entries from the collection entirely.

Memory Footprint

Optional is a box and consumes extra 16 bytes since it also adds one level of reference redirection it potentially adds to GC pressure and cache misses.

Adapting Between Null and Optional

Sometimes you need to adapt Optional-using code to code that wants null,

or vice-versa

• If you have a nullable reference and you need an Optional

Optional<T> opt = Optional.ofNullable(ref)

• If you have an Optional and you need a nullable reference

opt.orElse(null)

Optional is not serializable

Even though Guava Optional is serializable, Java optional is not serializable by design.

Usage at Whatfix

At Whatfix, we use Optional as the library method return value of functions when a return value might be absent.