网站Logo 苏叶的belog

Optional类

wdadwa
0
2026-03-05

一、Optional 类

OptionalJava 8 引入的一个容器类,用来表示 一个值可能存在,也可能不存在

它的核心目的是:

避免显式的 null 判断,从而减少 NullPointerException

传统代码:

User user = getUser();
if (user != null) {
    System.out.println(user.getName());
}

使用 Optional

Optional<User> userOpt = getUser();
userOpt.ifPresent(user -> System.out.println(user.getName()));

Optional 本质上是一个 值容器(Value Container)

Optional
   ├── 有值 (value)
   └── 空值 (empty)

二、创建 Optional 对象

Optional 提供了三种常见的创建方式。

1 Optional.empty()

创建一个 空 Optional

Optional<String> emptyOpt = Optional.empty();

适用于:

  • 方法返回空值
  • 表示明确的不存在

2 Optional.of()

创建一个 必须非空的 Optional

如果传入 null,会抛出 NullPointerException

Optional<String> opt = Optional.of("Hello");

错误示例:

Optional.of(null); // 抛出 NullPointerException

适用场景:

  • 明确知道值 一定不为 null

3 Optional.ofNullable()

创建一个 允许为 null 的 Optional

Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);

如果值为 null

Optional.empty()

企业开发中:

99% 使用 ofNullable

三、判断 Optional 是否存在值

1 isPresent()

判断是否存在值。

Optional<String> opt = Optional.of("Hello");

if (opt.isPresent()) {
    System.out.println(opt.get());
}

但这种写法 并不推荐

原因:

isPresent + get = 传统 null 判断写法

2 ifPresent()

如果值存在,则执行操作。

Optional<String> opt = Optional.of("Hello");

opt.ifPresent(value -> {
    System.out.println(value);
});

推荐写法:

opt.ifPresent(System.out::println);

四、获取 Optional 的值

1 get()

直接获取值。

String value = opt.get();

如果为空:

NoSuchElementException

开发中不推荐使用 get()

原因:

get() == 可能抛异常

2 orElse()

如果为空返回默认值。

String value = opt.orElse("Default");

示例:

Optional<String> opt = Optional.empty();

String value = opt.orElse("Default Value");

输出:

Default Value

3 orElseGet()

通过 Supplier 获取默认值。

String value = opt.orElseGet(() -> "Default Value");

区别:

方法特点
orElse默认值会提前计算
orElseGet只有为空时才执行

示例:

opt.orElse(expensiveMethod());
opt.orElseGet(() -> expensiveMethod());

推荐:

优先使用 orElseGet

4 orElseThrow()

如果为空,抛出指定异常。

String value = opt.orElseThrow(() ->
        new IllegalArgumentException("Value not present"));

常见写法:

User user = userOpt.orElseThrow(() ->
        new RuntimeException("用户不存在"));

五、Optional 的转换操作

Optional 的一个重要能力是 函数式转换


1 map()

如果存在值,执行转换。

Optional<String> opt = Optional.of("Hello");

Optional<Integer> lengthOpt = opt.map(String::length);

结果:

Optional[5]

获取:

System.out.println(lengthOpt.orElse(0));

2 flatMap()

用于 避免 Optional 嵌套

错误写法:

Optional<Optional<Integer>>

正确写法:

Optional<String> opt = Optional.of("Hello");

Optional<Integer> lengthOpt =
        opt.flatMap(v -> Optional.of(v.length()));

区别:

方法返回
mapOptional
flatMapOptional<Optional>

六、Optional 过滤

filter()

如果满足条件,保留值,否则返回空。

Optional<String> opt = Optional.of("Hello");

Optional<String> result =
        opt.filter(value -> value.startsWith("H"));

示例:

result.ifPresent(System.out::println);

输出:

Hello

不满足条件:

Optional.empty()

七、Java 9 新增方法

1 ifPresentOrElse()

值存在执行一个逻辑,否则执行另一个。

opt.ifPresentOrElse(
        value -> System.out.println("Value: " + value),
        () -> System.out.println("Value not present")
);

2 stream()

将 Optional 转换为 Stream。

Optional<String> opt = Optional.of("Hello");

opt.stream().forEach(System.out::println);

适用于:

Stream + Optional 组合

示例:

List<Optional<String>> list = List.of(
        Optional.of("A"),
        Optional.empty(),
        Optional.of("B")
);

list.stream()
        .flatMap(Optional::stream)
        .forEach(System.out::println);

输出:

A
B

八、开发最佳实践

1 不要用 Optional 作为字段

错误:

class User {
    Optional<String> name;
}

正确:

class User {
    String name;
}

原因:

  • 序列化问题
  • ORM 不支持
  • 增加复杂度

2 不要作为方法参数

错误:

void save(Optional<String> name)

正确:

void save(String name)

3 Optional 只用于返回值

推荐:

Optional<User> findUser(Long id)

4 不要滥用 Optional

错误:

Optional.of(user)

正确:

Optional.ofNullable(user)

九、使用示例

例如:

查询用户。

传统写法:

User user = userRepository.findById(id);

if (user == null) {
    throw new RuntimeException("用户不存在");
}

return user.getName();

Optional 写法:

return userRepository.findById(id)
        .map(User::getName)
        .orElseThrow(() -> new RuntimeException("用户不存在"));

优势:

  • 无 null 判断
  • 代码更简洁
  • 函数式风格

十、Optional 常用方法总结

方法作用
of创建非空 Optional
ofNullable创建可能为空 Optional
empty创建空 Optional
isPresent是否存在值
ifPresent存在时执行
get获取值(不推荐)
orElse默认值
orElseGetSupplier 默认值
orElseThrow为空抛异常
map转换
flatMap避免嵌套
filter过滤
动物装饰