Skip to content

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!

注意事项

  1. 不要将 Optional 用作方法参数或类的字段,它主要设计用于方法返回值。
  2. 避免过度使用 Optional,简单的 null 检查有时比复杂的 Optional 链式调用更易读。
  3. 不要使用 isPresent() 然后立即调用 get(),这与直接进行 null 检查没有本质区别。
  4. 优先使用 ifPresent()orElse()orElseGet() 等方法,而不是显式检查 isPresent()
  5. Optional 是一个值基类(value-based),避免使用身份敏感操作(如 ==、同步等)。

Power by VuePress & vuepress-theme-plume