Optional 的核心价值在于通过 flatMap/map/orElse 等组合操作实现空值的声明式、内聚化流转,而非替代 if 判空;应封装 safeGetXXX 方法下沉空处理逻辑,慎用 orElseThrow。

用 Optional 替代多重 if (obj != null) 并不能自动消除判空,关键在于**改变调用链的构建方式**——把“防御性检查”转为“可选值的声明式流转”,让空值处理内聚、延迟且显式。
别把 Optional 当成 null 的包装器
常见误区是这样写:
Optional<User> userOpt = Optional.ofNullable(user);
if (userOpt.isPresent()) { ... }
这和直接判空没区别,还增加了对象开销。Optional 的价值在 flatMap / map / orElse 等组合操作中体现,用于安全穿透嵌套结构。
用 flatMap 拆解多层对象访问
比如要取 user.getProfile().getAddress().getCity(),传统写法需 3 层判空;用 Optional 可写成:
String city = Optional.ofNullable(user)
.flatMap(u -> Optional.ofNullable(u.getProfile()))
.flatMap(p -> Optional.ofNullable(p.getAddress()))
.map(a -> a.getCity())
.orElse("未知城市");
每一步 flatMap 都自动跳过 null,无需显式 if;map 只在非空时执行,逻辑清晰、不可绕过。
把判空逻辑提前封装进领域方法
不要在业务代码里反复写 Optional.ofNullable(...).flatMap(...)。应在实体或工具类中提供语义化方法:
User::safeGetCity() → Optional<string></string>Order::getLatestPaymentDate() → Optional<localdatetime></localdatetime>
业务层直接链式调用:order.getLatestPaymentDate().filter(t -> t.isAfter(weekAgo)).isPresent(),空值处理完全下沉,上层只关注“有没有符合条件的支付时间”。
谨慎使用 orElseThrow,优先用 orElse 或 orElseGet
避免无意义异常:
- ❌
.orElseThrow(() -> new RuntimeException("地址为空"))—— 违背 Optional 设计初衷 - ✅
.orElse("北京")(默认值明确) - ✅
.orElseGet(this::getDefaultCity)(延迟计算,适合重逻辑)
只有当“空值代表严重业务异常且必须中断流程”时,才用 orElseThrow,并配具体业务异常类型,如 NoDeliveryAddressException。

















