Java 8 Optional Overview - Prevent NullPointerException
- schick09
- Oct 28, 2023
- 3 min read
Updated: Apr 25, 2024
We’ve all experienced them. No matter how good your junits are. No matter how extensive your PIT testing seems to be. Sooner or later you will encounter this nasty runtime exception in production. Depending on the quality of your logging and alerting, you may or may not even know they are happening. But your customers will, so let’s deal with these suckers once and for all.
Production java code is riddled with object graphs that are nested several levels deep. The data item you want to access may be 2 or 3 levels down. Accessing that data item involves traversing through other objects that may or may not be there. If you’re trying to access the object at level 3 and the object at level 2 happens to be null, the NullPointerException is thrown.
Enter java.util.Optional – a feature that was introduced in Java 8. Using Optional in your code services two purposes:
It’s a self-documenting way of telling readers of your code that “this object may not have a value in it – expect it to be null sometimes”
Whenever you want to access this object, you will need to explicitly check to see if it has a value or not (because, you know, it might be null….)
Let’s take a look at an example to illustrate how to use Optional.
In this scenario, we have called a REST API and received a response (RestServiceResponse). This response consists of a nested object graph that looks like this:
RestServiceResponse
Bank
AccountHolder
List<Accounts>
We are interested in accessing the List<Accounts> to use for later processing. To access the List<Accounts> we would have to first access the Bank, then the AccountHolder, then the List of Accounts. The problem is, the Bank and/or AccountHolder variables might be null, which would throw a NullPointerException.
Traditionally you may have seen a long and ugly statement (or some variation of the same) that looks something like this:
if (restServiceResponse != null && restServiceResponse.getBank() != null && restServiceResponse.getBank().getAccountHolder() != null) { return restServiceResponse.getBank().getAccountHolder().getAccounts(); }
This will work (or some other variation of the same – this is just one example), but it doesn’t fulfill the two benefits listed above of using Optional. So let’s rewrite this statement using java.util.Optional:
return Optional.ofNullable(restServiceResponse) .map(RestServiceResponse::getBank) .map(Bank::getAccountHolder) .map(AccountHolder::getAccounts) .orElse(Collections.emptyList());
Let's break this down.
The first line gets us an Optional of the RestServiceResponse object. This object may or may not be null. The Optional<RestServiceResponse> will contain a value variable whose value Is either the RestServiceResponse object or ‘null’.
In the second line, the 'map' method is called on Optional<RestServiceResponse>. This method basically says “If this Optional’s value isn’t null, then call the method I’m asking you to call on that Optional and return me an Optional of that type (in this case Optional<Bank>). If Optional<RestServiceResponse> has a value=null, then an Optional.empty is returned. Optional.empty has a value=null.
The process is then repeated in the third line. If the .map(Bank::getAccountHolder) is called on an Optional.empty (because Bank happened to be null in this case), then an Optional.empty is returned and the process continues. If .map(Bank::getAccountHolder) is called on an Optional<Bank> with a valid value, then an Optional<AccountHolder> is returned.
The process keeps going until you get to the .orElse(Collections.emptyList()) statement. If this statement is called on an Optional.empty, it will return whatever default value is in this method’s arguments (in this case, that’s Collections.emptyList()). If this .orElse statement is called on an Optional<List<Accounts>> with a valid value, then it will return the List<Accounts> value to the caller.
To see the code in action and try it out yourself, please visit my GIT repository -- https://github.com/daveschickconsulting/funwithoptionals

Comments