Optional

Optional<T> is a container object that either holds a non-null value or is empty. Added in Java 8, it was designed as a better return type than null for methods that may not produce a result β€” forcing the caller to think about the empty case at compile time.

Creating and consuming

Optional<User> findById(long id) {
    return Optional.ofNullable(db.find(id));  // null β†’ empty, non-null β†’ present
}

Optional<User> u = findById(42);
if (u.isPresent()) {
    System.out.println(u.get().getName());
}

// Idiomatic:
u.ifPresent(user -> System.out.println(user.getName()));

String name = u.map(User::getName).orElse("Unknown");

u.orElseThrow(() -> new NotFoundException("user " + 42));

Chaining

Optional<String> city = findById(42)
    .map(User::getAddress)
    .map(Address::getCity);

When to use Optional

  • Return type β€” for methods where absence is a normal outcome (lookups, searches).
  • Stream operations β€” findFirst, findAny, reduce return Optional.

When NOT to use Optional

  • Field types β€” don't store an Optional in a class field. Use nullability annotations or a more specific empty representation.
  • Method parameters β€” overload the method or use a required parameter; Optional as a parameter is awkward for callers.
  • Collections β€” return an empty List / Set, not Optional<List>.