Optional
Represent "maybe a value" explicitly and stop writing null checks everywhere.
What you’ll learn
- Why Optional exists
- map, filter and orElse
- orElseThrow for required values
- Where not to use Optional
The problem with null
String city = user.getAddress().getCity().toUpperCase();If any of those return null, you get a NullPointerException. Worse, nothing in the method signatures warned you. Optional makes "this might be missing" part of the type.
Optional<User> findByEmail(String email);Now every caller has to decide what happens when the user isn't found.
Creating an Optional
Optional.of(value); // value must not be null
Optional.ofNullable(value); // empty if value is null
Optional.empty();Using an Optional
String city = repo.findByEmail(email)
.map(User::address)
.map(Address::city)
.map(String::toUpperCase)
.orElse("UNKNOWN");Each map only runs if there's a value, so the chain safely short-circuits.
| Method | Does |
|---|---|
map(fn) | Transform the value if present |
filter(pred) | Keep the value only if it matches |
orElse(x) | Value, or a default |
orElseGet(() -> x) | Value, or a lazily computed default |
orElseThrow() | Value, or throw |
ifPresent(fn) | Run a side effect if present |
orElseThrow for required values
In a Spring Boot service, a missing entity is usually an error:
public User getUser(long id) {
return repo.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}Don't do this
if (opt.isPresent()) return opt.get(); is just a null check with extra steps. Reach for map, orElse and orElseThrow instead.
Where not to use Optional
- Fields — use a nullable field or a sensible default.
- Method parameters — overload the method instead.
- Collections — return an empty list, never
Optional<List<T>>.
Optional was designed for return types.
QWhat's the difference between orElse and orElseGet?+
orElse(x) always evaluates x, even when the Optional has a value. orElseGet(supplier) only calls the supplier when the Optional is empty — use it when the default is expensive to compute.
Key takeaways
- Use
Optionalas a return type for values that may be absent. - Chain
map/filterand finish withorElseororElseThrow. - Avoid
isPresent()+get().
Finished this lesson?
Mark it complete to move forward on your roadmap.