Unravel › Java concepts › Generics and functional
Optional and null safety
Optional<T> is a box that holds a value or nothing.
Learn these first
At a glance
A parcel that might be empty.
- 1Create with Optional.of(x) (x must not be null), Optional.ofNullable(x) or Optional.empty()
- 2Unwrap safely: orElse(default), orElseGet(() -> compute()), orElseThrow(() -> new NotFound()), ifPresent(x -> ...)
- 3Transform without unwrapping: map(User::getEmail), filter(e -> e.endsWith("@x.com")), flatMap(...)
- orElse(expensive()) always evaluates its argument, even when a value is present; use orElseGet for anything costly or with side effects
- get() on an empty Optional throws, so calling it without isPresent() just moves the null problem
- Optional is a final value-based class with a single nullable field; empty() returns one shared instance
Optional<User> user = repo.findByEmail(email);String name = user.map(User::getName).orElse("guest");user.ifPresent(u -> log.info("found {}", u.getId()));- line 1 uses Optional, the core of Optional and null safety
- line 2 uses orElse, the core of Optional and null safety
- line 3 uses ifPresent, the core of Optional and null safety
Read the full explanation (about 1 min)
Optional<T> is a box that holds a value or nothing. Returning it from a method tells the caller "this may be absent" and forces them to decide what to do, instead of risking a surprise NullPointerException.
A mental model
A parcel that might be empty. You open it and say what to do in both cases: "if there is a gift, use it; otherwise use this default".
How it works
Create with Optional.of(x) (x must not be null), Optional.ofNullable(x) or Optional.empty().
Unwrap safely: orElse(default), orElseGet(() -> compute()), orElseThrow(() -> new NotFound()), ifPresent(x -> ...).
Transform without unwrapping: map(User::getEmail), filter(e -> e.endsWith("@x.com")), flatMap(...).
Going deeper
orElse(expensive()) always evaluates its argument, even when a value is present; use orElseGet for anything costly or with side effects.
get() on an empty Optional throws, so calling it without isPresent() just moves the null problem. Prefer orElseThrow with a meaningful exception.
Optional is meant for return values. Do not use it for fields, method parameters or collections (return an empty list, not Optional<List>).
Under the hood
Optional is a final value-based class with a single nullable field; empty() returns one shared instance. It adds one small object allocation, which the JIT can often remove.
Common mistakes
get()without checking.orElsewith an expensive call.- Optional as a parameter or field.
- Wrapping then immediately calling
isPresent()andget(), which is just a null check with extra steps.
How Unravel recognises it
When you paste code, Unravel looks for these signs of optional and null safety. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
Optional - Method calls:
ofNullable()orElse()orElseGet()orElseThrow()ifPresent()isPresent()requireNonNull()
Part of a learning path
- Modern Java: lambdas and streams · previous: Streams · next: StringBuilder and string building
Related concepts
Frequently asked questions
What is Optional and null safety?
Optional<T> is a box that holds a value or nothing. Returning it from a method tells the caller "this may be absent" and forces them to decide what to do, instead of risking a surprise NullPointerException.
What are the most common mistakes with Optional and null safety?
get() without checking. orElse with an expensive call. Optional as a parameter or field. Wrapping then immediately calling isPresent() and get(), which is just a null check with extra steps.
How can I see Optional and null safety in real code?
Paste your own Java into Unravel and it will point out where optional and null safety appears, explain how it works at the detail level you choose, and draw the flow of the code around it.