Optional 的核心是将“值可能为空”显式纳入类型系统,强制编译时处理空值分支,而非消灭 NullPointerException;它适用于数据库查询等场景,支持 map/flatMap 链式转换、orElseThrow 明确异常、禁用 get(),但不能替代领域建模。

用 Optional 不是为了“消灭” NullPointerException,而是把“值可能为空”这个事实显式地写进类型系统里,让空值检查从运行时崩溃变成编译时约束和逻辑分支的自然组成部分。
用 Optional 包装可能为空的返回值
把原本可能返回 null 的方法,改为返回 Optional。例如数据库查询、配置读取、Map 查找等场景:
- 不要写
User getUserById(Long id)(调用方必须自己判空) - 改写为
Optional(契约即语义:查不到就是空,不是异常)findUserById(Long id)
这样调用方无法忽略“不存在”的情况——不处理 Optional 就无法拿到 User,编译器会强制你面对它。
用 map/flatMap 链式转换,避免嵌套判空
传统方式要层层判空:if (user != null && user.getProfile() != null && user.getProfile().getAvatar() != null)。用 Optional 可以平铺表达依赖关系:
findUserById(123).map(User::getProfile).map(Profile::getAvatar).orElse("default.png")- 任意一环为
empty,整个链自动短路,最终得到默认值或抛出自定义异常
每个 map 都是“如果存在,就做这件事”,语义清晰,无副作用,也不需要临时变量或 if 块。
用 orElseThrow 替代隐式 null 检查
当业务逻辑中“本该有值却为空”属于错误路径时,不要用 orElse(null) 再触发 NPE,而是主动抛出带上下文的异常:
findOrder(id).orElseThrow(() -> new OrderNotFoundException("Order " + id + " not found"))- 异常信息明确,堆栈可追溯,且调用方能统一捕获特定业务异常,而不是被 NPE 扰乱控制流
不滥用 get(),拒绝“又回到原点”
Optional.get() 是反模式——它和直接用 obj.method() 一样危险,只是把 NPE 延迟到运行时。应始终优先使用:
-
ifPresent(...)(有值才执行) -
map/filter/flatMap(转换或过滤) -
orElse / orElseGet / orElseThrow(提供备选路径)
只有在你 100% 确认值存在(比如刚调过 isPresent()),且代码处于调试或测试阶段时,才考虑 get() ——生产代码里几乎不该出现。










