Optional
Represent maybe-missing values without null: map, filter, orElse, orElseThrow and good practice.
Tony Hoare, who invented the null reference, called it his "billion-dollar mistake". In Java, NullPointerException is the most common runtime error, mostly because a method returned null and the caller forgot to check. Optional<T> (Java 8+) is a container that either holds a value or is empty, making "there might be no result" explicit in a method's type.
The problem#
Nothing in the signature User findByEmail(String) warns the caller. Compare:
Now the type itself says "maybe there's a user, maybe not", and the compiler won't let you treat an Optional<User> as a User.
Creating Optionals#
Getting the value out#
Transforming: map, flatMap, filter#
Like a stream with at most one element, Optional supports transformation without unwrapping:
map(fn): transform the value if present. Iffnreturnsnull, the result is empty, which makes chains through nullable fields safe.flatMap(fn): use whenfnitself returns anOptional, to avoidOptional<Optional<T>>.filter(predicate): keep the value only if it matches.or(supplier)(Java 9+): supply an alternativeOptional.
Compare the null-checking version of city1:
Optional and streams#
Many stream operations return Optional, and Optional.stream() (Java 9+) turns an optional into a zero- or one-element stream, which is handy for skipping empties:
Primitive optionals#
OptionalInt, OptionalLong and OptionalDouble avoid boxing. They are returned by IntStream.max(), average() and similar:
Good and bad uses#
Do:
- Return
Optional<T>from methods that may legitimately find nothing:findById,findFirst,parse. - Chain
map/filter/orElseinstead of unwrapping early. - Use
orElseThrowwhen absence is truly an error.
Don't:
- Return
nullfrom a method declared to returnOptional. That defeats the purpose. - Use
Optionalfor fields, method parameters or collection elements. For collections, return an empty collection instead ofOptional<List<T>>. - Write
if (opt.isPresent()) { x = opt.get(); }. It's just a null check in disguise; usemap/orElse/ifPresent. - Wrap everything in
Optional. It's an object allocation and adds noise for values that are never missing.
Spring Data repositories use exactly this style: Optional<User> findById(Long id).
Common mistakes#
- Calling
get()without checking, which turns an NPE into aNoSuchElementException. - Using
orElse(expensiveCall())when you meantorElseGet. Optional.of(possiblyNull)instead ofofNullable.- Comparing optionals with
==; useequals, or compare the contained values.
What's next#
Next we tackle a topic every application deals with: dates and times, using the modern java.time API.
Check your understanding
Quick quiz
1.What is the difference between
Optional.of(x)andOptional.ofNullable(x)?2.Why might
opt.orElse(loadFromDatabase())be wasteful compared withopt.orElseGet(() -> loadFromDatabase())?3.Which is generally considered a good use of Optional?
Finished reading?
Mark this lesson complete to track your progress.