Java Optional 类详解
约 1238 字大约 4 分钟
2025-09-23
概述
Optional<T> 是 Java 8 引入的一个容器类,用于表示一个值可能存在或不存在。它的主要目的是解决空指针异常(NullPointerException)问题,提供一种更优雅的方式处理可能为 null 的值。
Optional 类提供了一系列方法来检查值是否存在、处理存在的值以及处理值不存在的情况,从而避免了显式的 null 检查和嵌套的条件判断。
构造方法
empty()
创建一个空的 Optional 实例。
// 创建一个空的Optional
Optional<String> emptyOpt = Optional.empty();
System.out.println(emptyOpt.isPresent()); // 输出: falseof(T value)
创建一个包含指定非 null 值的 Optional 实例。如果传入 null,则会抛出 NullPointerException。
// 创建包含非null值的Optional
Optional<String> nonEmptyOpt = Optional.of("Hello");
System.out.println(nonEmptyOpt.isPresent()); // 输出: true
// 传入null会抛出异常
try {
Optional<String> nullOpt = Optional.of(null);
} catch (NullPointerException e) {
System.out.println("抛出了NullPointerException");
}ofNullable(T value)
创建一个包含指定值的 Optional 实例,如果值为 null,则创建一个空的 Optional。
// 传入非null值
Optional<String> nonNullOpt = Optional.ofNullable("Hello");
System.out.println(nonNullOpt.isPresent()); // 输出: true
// 传入null值
Optional<String> nullOpt = Optional.ofNullable(null);
System.out.println(nullOpt.isPresent()); // 输出: false主要方法
get()
如果值存在,则返回该值;否则抛出 NoSuchElementException。
Optional<String> opt = Optional.of("Hello");
String value = opt.get();
System.out.println(value); // 输出: Hello
Optional<String> emptyOpt = Optional.empty();
try {
emptyOpt.get();
} catch (NoSuchElementException e) {
System.out.println("抛出了NoSuchElementException");
}isPresent()
如果值存在,则返回 true;否则返回 false。
Optional<String> opt = Optional.of("Hello");
System.out.println(opt.isPresent()); // 输出: true
Optional<String> emptyOpt = Optional.empty();
System.out.println(emptyOpt.isPresent()); // 输出: falseifPresent(Consumer<? super T> consumer)
如果值存在,则执行指定的消费函数;否则不做任何操作。
Optional<String> opt = Optional.of("Hello");
opt.ifPresent(s -> System.out.println("值存在: " + s)); // 输出: 值存在: Hello
Optional<String> emptyOpt = Optional.empty();
emptyOpt.ifPresent(s -> System.out.println("值存在: " + s)); // 无输出filter(Predicate<? super T> predicate)
如果值存在且满足指定的谓词条件,则返回包含该值的 Optional;否则返回空的 Optional。
Optional<String> opt = Optional.of("Hello");
// 过滤长度大于3的字符串
Optional<String> filteredOpt = opt.filter(s -> s.length() > 3);
System.out.println(filteredOpt.isPresent()); // 输出: true
// 过滤长度大于10的字符串
Optional<String> emptyFilteredOpt = opt.filter(s -> s.length() > 10);
System.out.println(emptyFilteredOpt.isPresent()); // 输出: falsemap(Function<? super T, ? extends U> mapper)
如果值存在,则对其应用指定的映射函数,并返回包含映射结果的 Optional;如果映射结果为 null,则返回空的 Optional。
Optional<String> opt = Optional.of("Hello");
// 将字符串转换为其长度
Optional<Integer> lengthOpt = opt.map(s -> s.length());
System.out.println(lengthOpt.get()); // 输出: 5
Optional<String> emptyOpt = Optional.empty();
Optional<Integer> emptyMappedOpt = emptyOpt.map(s -> s.length());
System.out.println(emptyMappedOpt.isPresent()); // 输出: falseflatMap(Function<? super T, Optional> mapper)
如果值存在,则对其应用指定的映射函数(该函数返回一个 Optional),并返回该结果;否则返回空的 Optional。与 map 方法不同,flatMap 不会对结果进行额外的包装。
// 定义一个将字符串转换为Optional<Integer>的函数
Function<String, Optional<Integer>> stringToLength = s -> Optional.of(s.length());
Optional<String> opt = Optional.of("Hello");
Optional<Integer> lengthOpt = opt.flatMap(stringToLength);
System.out.println(lengthOpt.get()); // 输出: 5
Optional<String> emptyOpt = Optional.empty();
Optional<Integer> emptyFlatMappedOpt = emptyOpt.flatMap(stringToLength);
System.out.println(emptyFlatMappedOpt.isPresent()); // 输出: falseorElse(T other)
如果值存在,则返回该值;否则返回指定的默认值。
Optional<String> opt = Optional.of("Hello");
String value1 = opt.orElse("Default");
System.out.println(value1); // 输出: Hello
Optional<String> emptyOpt = Optional.empty();
String value2 = emptyOpt.orElse("Default");
System.out.println(value2); // 输出: DefaultorElseGet(Supplier<? extends T> other)
如果值存在,则返回该值;否则调用指定的供应函数并返回其结果。
// 定义一个供应默认值的函数
Supplier<String> defaultSupplier = () -> "Default from Supplier";
Optional<String> opt = Optional.of("Hello");
String value1 = opt.orElseGet(defaultSupplier);
System.out.println(value1); // 输出: Hello
Optional<String> emptyOpt = Optional.empty();
String value2 = emptyOpt.orElseGet(defaultSupplier);
System.out.println(value2); // 输出: Default from SupplierorElseThrow(Supplier<? extends X> exceptionSupplier)
如果值存在,则返回该值;否则调用指定的供应函数并抛出其返回的异常。
// 定义一个供应异常的函数
Supplier<IllegalStateException> exceptionSupplier = () ->
new IllegalStateException("值不存在");
Optional<String> opt = Optional.of("Hello");
String value = opt.orElseThrow(exceptionSupplier);
System.out.println(value); // 输出: Hello
Optional<String> emptyOpt = Optional.empty();
try {
emptyOpt.orElseThrow(exceptionSupplier);
} catch (IllegalStateException e) {
System.out.println("捕获异常: " + e.getMessage()); // 输出: 捕获异常: 值不存在
}使用示例:综合运用
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
// 创建一个可能为null的字符串
String str = "Hello, Optional!";
// 使用ofNullable创建Optional
Optional<String> opt = Optional.ofNullable(str);
// 综合使用map、filter和ifPresent
opt.map(s -> s.toUpperCase())
.filter(s -> s.length() > 10)
.ifPresent(s -> System.out.println("处理后的值: " + s));
// 使用orElseThrow处理空值情况
String result = opt.orElseThrow(() -> new IllegalArgumentException("字符串不能为空"));
System.out.println("结果值: " + result);
}
}输出:
处理后的值: HELLO, OPTIONAL!
结果值: Hello, Optional!注意事项
- 不要将
Optional用作方法参数或类的字段,它主要设计用于方法返回值。 - 避免过度使用
Optional,简单的 null 检查有时比复杂的Optional链式调用更易读。 - 不要使用
isPresent()然后立即调用get(),这与直接进行 null 检查没有本质区别。 - 优先使用
ifPresent()、orElse()、orElseGet()等方法,而不是显式检查isPresent()。 Optional是一个值基类(value-based),避免使用身份敏感操作(如==、同步等)。