Java's Optional class eliminates explicit null checks by wrapping a potentially absent value within a container, thereby helping to prevent NullPointerException. Understanding how to construct, interrogate, and transform Optional instances is essential for writing cleaner, safer code.
Building Optional Instances
There are three primary ways to obtain an Optional object.
The empty() factory produces an Optional that holds nothing:
Optional<String> noValue = Optional.empty();
System.out.println(noValue); // Optional.empty
To create an Optional that is guaranteed to contain a non-null reference, use of(). Passing null here immediately raises NullPointerException:
Optional<String> wrappedName = Optional.of("沉默王二");
System.out.println(wrappedName); // Optional[沉默王二]
The most flexible factory is ofNullable(), which accepts any reference. If the supplied value is null, an empty Optional is returned; otherwise, the value is boxed inside a new Optionla. Internally this relies on a conditional check rather than a constructor that throws:
String maybeNull = null;
Optional<String> flexible = Optional.ofNullable(maybeNull);
System.out.println(flexible); // Optional.empty
Checking for Presence
The method isPresent() reports whether a value exists:
Optional<String> presentOpt = Optional.of("沉默王二");
System.out.println(presentOpt.isPresent()); // true
Optional<String> absentOpt = Optional.ofNullable(null);
System.out.println(absentOpt.isPresent()); // false
Executing Code When a Value Present
ifPresent() accepts a Consumer that runs only when a value is wrapped inside the Optional:
Optional<String> target = Optional.of("沉默王二");
target.ifPresent(val -> System.out.println(val.length()));
Starting from Java 9, ifPresentOrElse takes two callbacks—one for the non-empty case and one for the empty case:
Optional<String> sample = Optional.of("沉默王二");
sample.ifPresentOrElse(
v -> System.out.println(v.length()),
() -> System.out.println("为空")
);
Supplying Default Values with orElse
orElse() returns the contained value when present, or the provided fallback when empty. The fallback matches the generic type:
String missingName = null;
String resolved = Optional.ofNullable(missingName).orElse("沉默王二");
System.out.println(resolved); // 沉默王二
Filtering Based on Predicates
The filter method evaluates a Predicate against the value. If the predicate returns false, the result is an empty Optional:
String candidate = "12345";
Optional<String> checked = Optional.ofNullable(candidate)
.filter(pwd -> pwd.length() > 6);
System.out.println(checked.isPresent()); // false
Multiple predicates can be combined using logical operations. The following example chains length checks with and:
Predicate<String> longerThanSix = pwd -> pwd.length() > 6;
Predicate<String> shorterThanTen = pwd -> pwd.length() < 10;
String updatedCandidate = "1234567";
Optional<String> resultOpt = Optional.ofNullable(updatedCandidate)
.filter(longerThanSix.and(shorterThanTen));
boolean isValid = resultOpt.isPresent();
System.out.println(isValid); // true
Using Optional and its combinators like filter avoids deeply nested if-else blocks and makes the logic more declarative.