orElse无条件立即执行默认值表达式,orElseGet仅在Optional为空时才调用Supplier;前者适用于简单无副作用的默认值,后者适合耗时或有副作用的按需构造场景。

Java 中 Optional 的 orElse 和 orElseGet 都用于提供空值时的默认值,但它们的执行时机和适用场景有本质区别:前者**无条件执行**,后者**仅在 Optional 为空时才调用**。合理选择能避免不必要计算、提升性能,甚至防止异常。
orElse:立即求值,适合简单、无副作用的默认值
orElse(T other) 会在调用时**立刻计算并返回参数值**,无论 Optional 是否为空。这意味着即使 Optional 有值,传入的默认值表达式也会被执行。
- 适用于字面量、常量或轻量级对象(如
"default"、0、new ArrayList()) - 不适合含 I/O、数据库查询、耗时计算或可能抛异常的逻辑
- 示例:
optionalString.orElse("N/A")—— 安全、简洁 - 危险示例:
optional.orElse(expensiveMethod())—— 即使 optional 非空,expensiveMethod()仍会被调用
orElseGet:延迟求值,适合需按需构造的默认值
orElseGet(Supplier extends T> supplier) 接收一个 Supplier,**仅当 Optional 为 empty 时才执行该 Supplier 的 get() 方法**。这是真正的懒加载。
- 推荐用于创建新对象、调用外部服务、读配置、日志记录等有开销或副作用的操作
- 可配合方法引用或 Lambda 使用,语义清晰
- 示例:
optional.orElseGet(() -> fetchDefaultFromDB()) - 更简洁写法:
optional.orElseGet(this::createFallbackUser)
关键对比:看是否触发了默认值逻辑
下面代码直观体现差异:
Optional<String> opt = Optional.of("hello");
// orElse 强制执行字符串拼接(浪费)
String s1 = opt.orElse("fallback: " + System.currentTimeMillis());
// orElseGet 完全不执行 lambda(高效)
String s2 = opt.orElseGet(() -> "fallback: " + System.currentTimeMillis());
运行后,s1 中拼接已发生;s2 中 lambda 根本未执行。
实际应用建议
- 默认值是常量或构造成本极低 → 用
orElse,代码更直白 - 默认值依赖外部资源、有状态操作或可能失败 → 必须用
orElseGet - 避免在
orElse中写复杂表达式,IDE 通常会警告“Unnecessary computation in orElse” - 若默认逻辑需捕获异常,
orElseGet更易处理(可在 lambda 内 try-catch)

















