DeepakBhalla

How to use Java 8 Optionals

By Deepak Bhalla Sat 30 April 2016 4 min read

Java 8 Optionals

Optionals are a Java 8 featured container type wrapping. Optionals can be thought of as a way of simplifying the representation of potential nothingness.

public interface AccountRepository {
    public Optional<Account> findUserByEmail(String email)
}
An email look up in an Account Repository

According to the documentation a Java 8 Optional is:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

It is not similar to existing "option" or "maybe" programming paradigms. An Optional is not a variable which is optional but rather a container which may or may not return a value.

Why use an optional

The main reason to care about Optionals is to prevent the careless use of null and null checkes which can cause a huge number of preventable issues.

Ambiguity

Optional can prevent the ambiguity that multiple potential null values implicitly create.

Account account = AccountService.getByEmail("test@deepakrb.com");

if (account == null) {
    // Handle this potential situation
}
A typical null check

The AccountService.getByEmail() call can return null because AccountService returns null or getByEmail() returns null. The if block then becomes an ambiguous catch all of many different events. A better check using Optional:

Optional<Account> accountResult = AccountService.getByEmail("test@deepakrb.com");
Account account = accountResult.orElse(Account.getAnonymouse());
A typical optional check

The largest advantage of Optional is therefore its ability to reduce ambiguity in code. You are forced by the compiler to consider the accessing of a variable.

Verboseness

Optional can also increase the verboseness of your code. If you return an Optional you make the end user of your API understand what potential results.

String var_email = "test@deepakrb.com";
Account.getByEmail(var_name);

When calling the above method the developer is in charge of the variable var_name so they have an explicit understanding of whether that variable is null or not. When they call Account.getByEmail(var_name) they may have no understanding of how the getByEmail method is implemented. They may only have access to its interface and the method could be considered a black box. Optional helps the end user understand the potential return types of the method.

Optionals in practice

There are multiple instances where Optional makes sense. For instance, a search or filtering which could have no result are perfect opportunities to take advantage of Optional:

Optional<Account> accountResult = AccountService.getByEmail("test@deepakrb.com");;
Account account = accountResult.orElse(Account.getAnonymouse());
The orElse method helps prevent multiple account variable checks
public
return Optional.ofNullable(AccountService.getAllAccounts())
    .map(account -> account.getAccountName())
    .filter(Optional::isPresent)
Using Optionals functionally to get all names

It is very easy to use Optional incorrectly, there is nothing stopping you from making Optional just as reliable as null checks.

Avoid using it like null

There is little point in using Optional like a null check:

if (accountResult.isPresent()) {
    // Is present
} else {
    // Not present
}

You benefit very little from Optionals method, and are in fact simply increasing your memory footprint.

Avoid get

Java 8 .get() is actually closer to getWhenPresent() (Stuart Marks) and will throw an unchecked NoSuchElementException if there is no value in the Optional. Use isPresent, orElse, and orElseGet to prevent thrown exceptions. If you want to throw a custom exception you can use orElseThrow.

End Notes

Using Optional can seem like a more stringent null check but what we get in exchange is compile time checks, and a consistent way of dealing with null regardless of type. The Optional API and Java 8 make it easy to create functional design patterns that are able to cope with null or non null values. However, optionals are not going to remove the use of null, you should know when and when not to use optionals. null is unavoidable but for all its faults is cheap and memory efficient.

But you should still ask you, why there might be no result and if it is OK to have no result. Not only from a technical perspective but also from the business perspective.

Anti Pattern: Don’t use Optionals for data repositories - Thomas Uhrig

If we look back at Map.get we see that it is legitimate for a Map to contain null as a value for a key. This is distinct from there not being a mapping at all. Java (as part of its design) allows null to inhabit any reference type – but Optional specifically prohibits null being contained in it!

Why java.util.Optional is broken - Jed Wesley-Smith

Deepak Bhalla