Written on September 05, 2016
So we’ve already talked a little bit about the improvements in Java 9 to two
features that were introduced in Java 8: Streams and Collectors.
But what about one of our other Java 8 friends:
Optional. At Iteratrlearning
we’re real fans of the
Optional type. We’ve found that, if used well, it can
make your code more explicit and reduce the scope for bugs.
Of course nothing is perfect.
Optional in Java 8 was missing a few features
that have been improved upon in Java 9 and that’s what we’ll be talking about
If you’ve been using Java 8’s Stream API in conjunction with the Optional class then you might have hit a situation where you want to replace a stream of Optionals with values that are present. For example, let’s suppose you’ve got a set of settings that may be set by a user. You’ve implemented a
lookupSettingByName() method that returns an Optional
In this example we’re combining two optional methods to achieve our goal. We’ve used a
filter on the
isPresent() method in order to remove empty Optionals. We then unboxed the optionals that we knew had a value in with the
get() method call.
This is a functional solution, but we can streamline things in Java 9. Here a method on Optional has been added that returns a
Stream called, funnily enough,
stream(). That will give us a stream with an element in if the Optional has one, or empty otherwise. Let’s see how our code would look with this approach:
This new addition also means that it is simpler to integrate Optional with APIs expecting to work with Streams.
ifPresentOrElse method encodes a common pattern where you want to perform an action if an Optional value is present, or a different action if it’s absent. In order to understand it better we’ll take an example of someone trying to checkin to an airline flight and see how you would write this code both using null checks and also the
Our user provides us with a booking reference, which we lookup their booking with. If we have a booking associated with that reference then we can display the check-in page to them, otherwise we’ll just display a page explaining that their booking record is missing.
lookupBooking method were to return null in order to indicate that the booking is missing then our code might look like the following:
Now in Java 8 we could have refactored
lookupBooking to return an Optional value, which gave us an explicit indication that a booking may not be looked up. It also helps the user to think about the distinction between the booking being present and absent, rather than simply hoping that they have a null check. The simplest refactor for this code would have been to the following:
Now this pattern of taking an
Optional and calling
get() isn’t a particularly idiomatic use. In fact it basically leaves us with similar code to the null checked version. Ideally we want to be able to call a method on the
Optional that is appropriate for our use case. Effectively moving to a tell-don’t-ask style of coding.
Optional from Java 8 has an
ifPresent method that will invoke its callback if the value inside the
Optional is present, for example:
Unfortunately it doesn’t meet our needs here because it won’t handle the case where the value is absent and we want to display our missing booking page. This is the use case that Java 9’s
Optional addresses. We could refactor our original code as follows:
Another method that has been added to
Optional in Java 9 is the succinctly named
or() method. This method takes a function that creates an Optional as an argument. If the object that it gets invoked upon has a value present then it is returned, otherwise the function is invoked and its result returned.
This is particularly useful when you have a couple of methods that all return optionals and you want to return the first one that is present. Let’s suppose that we want to lookup information about client’s using a company identifier, such as their company number. Firstly we want to check our existing client datastore and see if the company is in there. If it isn’t we want to create a new client by looking up the information about the company from Companies House. Now it might be the case that the provided id is a typo from a user and couldn’t be looked up at all. If we suppose that our methods just return null in order to indicate that the value is missing then we might write the following code:
Now if someone refactors
findClient() to return an Optional, we can use the orElseGet() method from Java 8 which will only call our
lookupCompanyDetails() method if the Optional is absent. For example:
Unfortunately this still doesn’t model our use case correctly. Since the companyId may not correspond to an actual company identifier the
lookupCompanyDetails() method can still fail. If we’re going down the route of modelling failure using the
Optional type then we should also make that method return an
This is where the new
or() method comes into play. We get an
Optional<Client> back. If we could lookup the client in our database then that would be the value present, if it was a valid new company then that would be returned, if it was a typo then the
Optional box would be empty. Et voila:
There is an outstanding proposal to deprecate
Optional.get() and rename it to
something else. The full details of this proposal can be read
Despite this proposal having merit the schedule constraints mean that it is
unlikely to make Java 9, but might happen in Java 10.
We’ve talked about Java 8’s
Optional class is being improved in Java 9 with a
series of targeted method that each fill a missing use case. Unfortunately, the
Optional classes, such as
OptionalInt aren’t getting
all the same love - they have had
ifPresentOrElse() added, but
or(). They have always been missing some of the methods from
and are increasingly looking like poor cousins.