Java 8 都出了这么多年,为什么 Optional 还是没人用?

71 阅读3分钟

沉默是金,总会发光

大家好,我是沉默

写 Java,最怕的是什么?

答:空指针异常(NPE)

写 Java 这么多年,你是不是经常写这样的代码:

User user = getUserById(1);if (user != null) {    Address address = user.getAddress();    if (address != null) {        String city = address.getCity();        if (city != null) {            System.out.println(city.toUpperCase());        }    }}

一层层嵌套的 if 判空,像旋转楼梯,写着写着自己都崩溃。

这时,Java 8 给我们带来了一个救星 —— Optional

可现实是:Optional 出道十几年,却依然像个透明人,没人真正用。

这是它不好用,还是大家用错了?

**-**01-

为啥大家不用 Optional?

1. 习惯就是枷锁

  • 老程序员:if 写十几年了,手感比 Optional 好。
  • 新人:书上压根没重点讲 Optional,感觉可有可无。

2. 用错了,劝退

反例:

Optional<User> opt = Optional.ofNullable(user);if (opt.isPresent()) {    User u = opt.get();    // 干活}

这不还是 if (user != null) 吗?换汤不换药

3. 团队没共识

你在 service 层返回 Optional<User>,隔壁老王一脸懵:

Optional<User> result = userService.findUser(id);// 然后呢?咋取值?咋判空?咋处理没找到?

结果一顿 .get() + .orElse(null),回到原始社会。

4. 框架兼容差

  • MyBatis:查不到,直接 null

  • SpringBoot:接口返回 Optional<String>,前端压根接不了。

于是大家结论:Optional 很鸡肋?

- 02-

Optional 正确用法场景

场景 1:链式取值

告别瀑布 if,一行搞定:

String city = Optional.ofNullable(user)        .map(User::getAddress)        .map(Address::getCity)        .orElse("未知城市");

清晰、简洁,还不用担心漏判空。

场景 2:方法返回值表达“可能不存在”

public Optional<User> findActiveUserByEmail(String email) {    User user = userRepo.findByEmail(email);    if (user != null && user.isActive()) {        return Optional.of(user);    }    return Optional.empty();}

调用方一看:哦,可能没有,要处理。不用猜“文档在哪,这会不会返回 null?”

场景 3:替代默认值逻辑

传统写法:

String name = user.getName();if (name == null) {    name = "匿名用户";}

Optional 写法:

String name = Optional.ofNullable(user.getName())                      .orElse("匿名用户");

更优雅。

图片

- 03-

哪些地方千万别用 Optional?

参数类型

public void saveUser(Optional<User> user) { ... }

调用方会疯:传 null 还是传 Optional.empty()

**
**

实体类字段

public class User {    private Optional<String> email; // 灾难}

ORM、序列化全崩。

**
**

集合元素

List<Optional<String>> names; // 套娃地狱

**
**

接口返回给前端
Optional 是 Java 的概念,前端完全不懂。

图片

**-**04-

团队怎么推广 Optional?

  1. 统一规范
  • 查询方法:findById → Optional<User>
  • 取第一个:findFirstActive → Optional<Order>

  1. 写工具类降低门槛
public class Optionals {    public static <T> T orDefault(Optional<T> opt, T def) {        return opt.orElse(def);    }}

**
**3. 代码审查温和引导
看到嵌套 if,就说:
“这块可以用 Optional 简化下,要不要试试?”

**-**05-

Optional 的进阶操作

filter:条件过滤

Optional.ofNullable(user)        .filter(u -> u.getAge() >= 18)        .ifPresent(u -> System.out.println("成年用户:" + u.getName()));

**
**flatMap:避免嵌套 Optional

Optional<String> name = Optional.ofNullable(user)                .flatMap(u -> Optional.ofNullable(u.getNickName()));

**
**orElseThrow:语义化抛异常

User user = userService.findById(123)                .orElseThrow(() -> new UserNotFoundException("用户不存在"));

**-**06-

总结

Optional 的局限性

  • 性能上有点开销。
  • 深层嵌套对象,写起来依然麻烦。
  • JSON / RPC 序列化不可用。
  • 没团队共识时,容易变成异类。

所以:它只是工具,不是银弹。

使用场景对比表

场景推荐用法
链式取值✅ 大力用,告别嵌套 if
方法返回值✅ 表达“可能为空”
参数类型❌ 禁用
实体类字段❌ 禁用
集合元素❌ 禁用
接口返回给前端❌ 禁用

核心 takeaway

  • Optional 的核心价值:显式表达“可能不存在”。

  • 最佳场景:链式取值 + 方法返回值。

  • 不要滥用:参数、实体、集合、前端接口。

  • 推广秘诀:先规范,再引导。

学会用 Optional,不光是写代码优雅的问题,而是减少 NPE、提升代码可读性和团队协作效率的第一步。

**-**07-

粉丝福利

点点关注,送你互联网大厂面试题库,如果你正在找工作,又或者刚准备换工作。可以仔细阅读一下,或许对你有所帮助!

image.png

image.pngimage.png