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()); // 输出: false
of(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()); // 输出: false
ifPresent(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()); // 输出: false
map(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()); // 输出: false
flatMap(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()); // 输出: false
orElse(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); // 输出: Default
orElseGet(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 Supplier
orElseThrow(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),避免使用身份敏感操作(如==
、同步等)。