Java Optional
Java Optional is a container object that may hold one non-null value or may be empty. It is commonly used as a method return type when a result might not exist.
Optional does not remove every need for null, but it makes the possibility of a missing value visible in the type. Instead of returning null and hoping the caller remembers to check, a method can return Optional<String>, Optional<Integer>, or another optional type.
Creating Optional Values
The Optional class is in java.util. Use Optional.of(value) when the value must not be null. Use Optional.ofNullable(value) when the value might be null. Use Optional.empty() when there is no value.
| Method | Meaning |
|---|---|
Optional.of(value) |
Creates an optional with a non-null value |
Optional.ofNullable(value) |
Creates an optional that is empty if the value is null |
Optional.empty() |
Creates an empty optional |
Example: Returning a Possible Match
This program searches for a username. The method returns an Optional<String> because the requested user may not be in the list.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class Main {
public static Optional<String> findUser(List<String> users, String target) {
for (String user : users) {
if (user.equalsIgnoreCase(target)) {
return Optional.of(user);
}
}
return Optional.empty();
}
public static void main(String[] args) {
List<String> users = Arrays.asList("Mia", "Noah", "Ava");
Optional<String> result = findUser(users, "noah");
Optional<String> missing = findUser(users, "Liam");
result.ifPresent(user -> System.out.println("Found: " + user));
System.out.println("Missing value: " + missing.orElse("Guest"));
}
}
Output:
Found: Noah
Missing value: Guest
How the Example Works
The findUser method returns Optional.of(user) when it finds a match. If the loop finishes without a match, it returns Optional.empty(). The caller must then decide what to do with both cases.
The call to result.ifPresent(...) runs the lambda only when a value exists. The call to missing.orElse("Guest") gives a fallback value when the optional is empty.
Checking and Unwrapping
You can check an optional with isPresent(), but do not turn every optional into a longer version of a null check. Prefer methods that describe the action you want, such as ifPresent, orElse, orElseGet, map, and filter.
import java.util.Optional;
public class Main {
public static void main(String[] args) {
Optional<String> nickname = Optional.ofNullable("Sam");
Optional<String> emptyName = Optional.ofNullable(null);
System.out.println(nickname.isPresent());
System.out.println(nickname.orElse("Anonymous"));
System.out.println(emptyName.orElseGet(() -> "Generated Guest"));
}
}
Output:
true
Sam
Generated Guest
orElse uses the fallback value you provide. orElseGet accepts a supplier lambda and calls it only when the optional is empty, which is useful when creating the fallback takes work.
Transforming Optional Values
map transforms the value inside an optional when it exists. If the optional is empty, map simply returns another empty optional. filter keeps the value only if it matches a condition.
import java.util.Optional;
public class Main {
public static void main(String[] args) {
Optional<String> email = Optional.of("student@example.com");
String domain = email
.filter(value -> value.contains("@"))
.map(value -> value.substring(value.indexOf('@') + 1))
.orElse("unknown");
System.out.println(domain);
}
}
Output:
example.com
When to Use Optional
- Use
Optionalmainly for return values that may be missing. - Do not use
Optional.get()unless you already proved a value is present; otherwise it can throw an exception. - Avoid storing
Optionalin fields or using it for every parameter. A normal value, validation, or method overload is often clearer. - Use
OptionalInt,OptionalDouble, orOptionalLongfor optional primitive results.
Takeaway: Optional makes missing results explicit and gives you readable methods for handling the present and empty cases.
