Use Java Optional to model absent results deliberately, without turning it into a field, DTO, or control-flow replacement for every null check.
Optional is useful in Java when it makes absence explicit at an API boundary. It is less useful when it becomes decoration on fields, persistence models, DTOs, or internal control flow that would be clearer with direct code.
Good uses of Optional usually involve return values such as:
That is where the type carries meaning: “a result may legitimately be absent.”
Optional is often a bad fit for:
These uses tend to add wrapping noise without clarifying the design.
Idiomatic Optional code usually leans on:
mapflatMapfilterorElseGetinstead of constantly doing isPresent() followed by get().
1String label = customerRepository.findById(id)
2 .filter(Customer::isActive)
3 .map(Customer::displayName)
4 .orElse("inactive-or-missing");
This keeps absence handling closer to the value flow.
If an API returns Optional, callers should not still need a second sentinel or magic value to interpret absence. The type itself should already carry that meaning.
Optional helps when it clarifies a contract. It hurts when it is applied mechanically just to avoid the appearance of null.