必须用 Optional.ofNullable 而非 Optional.of,因为 ofNullable 对 null 安全,可显式暴露空值并支持链式判空与安全兜底;of 传 null 会立即抛 NPE,违背防御初衷。

用 Optional.ofNullable 包装三方库返回的值,本质是把“可能为空”的事实显式暴露出来,逼你在后续代码中主动处理空值,而不是等 NullPointerException 在运行时突然炸掉系统。
为什么不能直接用 Optional.of
Optional.of(null) 会立即抛出 NullPointerException,完全违背了“防御空值”的初衷。三方库返回 null 是常态,比如 Jackson 解析失败、Feign 调用超时返回 null、MyBatis 查询无结果时的字段映射等。必须用 ofNullable —— 它对 null 安全,输入 null 就返回空 Optional,不报错。
典型场景:链式调用前兜底
三方对象嵌套深(如 response.getData().getUser().getProfile().getAvatar()),任意一环为 null 就崩。改写为:
Optional.ofNullable(response)
.map(Response::getData)
.map(Data::getUser)
.map(User::getProfile)
.map(Profile::getAvatar)
.orElse("default-avatar.png");
每层 map 都在 Optional 内部做判空,null 会自动短路,最终安全 fallback。
配合 ifPresent 或 orElseThrow 做业务分流
不是所有空值都要给默认值。比如支付回调中,三方返回的订单号为 null,应明确拒绝而非塞个假单号:
-
Optional.ofNullable(thirdPartyOrder.getId()).filter(id -> !id.isEmpty()).ifPresent(this::processOrder);—— 有合法 ID 才处理 -
Optional.ofNullable(user).orElseThrow(() -> new BusinessException("用户不存在"));—— 空则抛业务异常,由上层统一捕获并返回友好提示
注意边界:Optional 不是万能胶水
它解决的是“调用链中某环节可能为空”的问题,不是替代空值校验逻辑:
- 不要把 Optional 当返回类型暴露给 Controller 层(Spring MVC 不支持自动解析 Optional 返回值)
- 数据库查询结果为 null,优先考虑 MyBatis 的
@Options(useGeneratedKeys = true)或 ResultMap 映射策略,而不是靠 Optional 包裹原始 ResultSet - 第三方 SDK 明确文档写了“失败时返回 null”,那就老实用
ofNullable;如果它返回的是自定义错误对象(如Result<t></t>),优先用其自带的isSuccess()判断,再取 data

















