orElse() 总是立即执行默认值表达式,造成资源浪费;orElseGet() 仅在 Optional 为空时惰性调用 Supplier 初始化,避免不必要开销。

关键在于:只有当 Optional 为空时,orElseGet() 才会执行 Supplier 中的初始化逻辑;而 orElse() 无论 Optional 是否为空,都会**先计算默认值**——这可能导致不必要的对象创建、IO 调用或耗时操作。
orElse() 会无条件执行默认值表达式
它接收一个具体值(而非函数),JVM 在调用 orElse() 前就必须求出该值。即使 Optional 有值,这个“默认值”也会被构造出来,然后被丢弃。
例如:
❌ 危险写法(即使 user 存在,new ExpensiveService() 仍被执行):ExpensiveService service = Optional.ofNullable(user)<br> .orElse(new ExpensiveService()); // 每次都 new,浪费资源
orElseGet() 延迟执行,只在需要时才初始化
它接收一个 Supplier
✅ 正确写法(user 不为 null 时,ExpensiveService 根本不会被创建):
ExpensiveService service = Optional.ofNullable(user)<br> .orElseGet(() -> new ExpensiveService()); // 按需创建
常见易错场景与改进建议
- 数据库连接或缓存查询:避免用 orElse(db.queryDefault()),改用 orElseGet(() -> db.queryDefault())
- 日志或监控埋点:不要 orElse(logAndReturnDefault()),否则日志总被打印;应 orElseGet(() -> { log.warn("fallback"); return default; })
- 外部 API 调用:orElse(callThirdPartyApi()) 是严重隐患;必须改为 orElseGet(() -> callThirdPartyApi())
- 简单常量无影响:orElse("default") 安全,因为字符串字面量无副作用;但 orElse(getDefaultString()) 仍有风险,应统一用 orElseGet
如何快速识别并修复
- 检查 orElse(...) 括号内是否含 new、方法调用、复杂表达式——是,则大概率应改 orElseGet
- IDE 通常会警告 “Argument of ‘orElse’ is a method reference or lambda that could be moved to ‘orElseGet’”
- 单元测试中可加断点或日志验证:对非空 Optional 调用后,初始化逻辑是否真的未触发

















