On this page
Optional
Optional<T> (since Java 8) is a container that may or may not hold a non-null value. It helps express absent values explicitly and reduces null-related bugs.
Creating Optional
Optional<String> present = Optional.of("Hello");
Optional<String> empty = Optional.empty();
Optional<String> nullable = Optional.ofNullable(getName()); // null-safe
| Method | Behavior if null |
|---|---|
Optional.of(value) |
Throws NullPointerException |
Optional.ofNullable(value) |
Returns Optional.empty() |
Optional.empty() |
Returns empty Optional |
Checking and Retrieving Values
Optional<String> opt = Optional.of("Java");
if (opt.isPresent()) {
System.out.println(opt.get());
}
// Preferred — avoids explicit isPresent/get
opt.ifPresent(System.out::println);
String value = opt.orElse("default");
String value2 = opt.orElseGet(() -> expensiveDefault());
String value3 = opt.orElseThrow(() -> new IllegalStateException("Not found"));
Transforming Optional
Optional<String> name = Optional.of(" alice ");
Optional<String> trimmed = name.map(String::trim);
Optional<Integer> length = name.map(String::length);
Optional<String> upper = name
.filter(s -> !s.isBlank())
.map(String::trim)
.map(String::toUpperCase);
flatMap
Use flatMap when the mapping function returns an Optional:
public Optional<User> findUserById(Long id) { ... }
Optional<String> email = findUserById(1L)
.flatMap(User::getEmail); // User.getEmail() returns Optional<String>
Optional in Method Returns
public Optional<User> findByEmail(String email) {
User user = database.lookup(email);
return Optional.ofNullable(user);
}
// Caller
findByEmail("[email protected]")
.ifPresent(user -> sendWelcomeEmail(user));
Optional Chains (Java 9+)
Optional<String> result = findUser(id)
.flatMap(User::getAddress)
.flatMap(Address::getCity)
.map(String::toUpperCase);
// Java 9: ifPresentOrElse
opt.ifPresentOrElse(
value -> System.out.println("Found: " + value),
() -> System.out.println("Not found")
);
// Java 10: orElseThrow() with no argument
String name = opt.orElseThrow(); // throws NoSuchElementException
Anti-Patterns — Do NOT
// ❌ Don't use Optional as a field
public class User {
private Optional<String> middleName; // Bad
}
// ❌ Don't use Optional as a method parameter
public void process(Optional<String> name) { } // Bad
// ❌ Don't call get() without checking
String s = opt.get(); // throws if empty
// ❌ Don't use Optional for collections — use empty collections instead
Optional<List<String>> items; // Bad — return List.of() instead
Best Practices
- Use
Optionalas a return type to signal “may not exist” - Never use
Optionalfor fields or method parameters - Prefer
orElseGet()overorElse()when the default is expensive to compute - Use
map/flatMap/filterto chain operations without null checks - Return
Optional.empty()instead of returningnull