因为orelse会立即执行默认值表达式,造成不必要的性能开销;orelseget则通过supplier实现惰性求值,仅在optional为空时才调用,避免冗余计算。

在使用 Apollo 配置中心时,常需要为关键配置项设置“降级策略”:当 Apollo 中未配置、配置为空、或拉取失败时,自动 fallback 到一个动态生成的默认值(而非固定字面量),这时 Optional.orElseGet 是比 orElse 更安全、更灵活的选择。
为什么不用 orElse 而用 orElseGet?
orElse(T other) 会在每次调用时**立即执行**参数表达式,无论 Optional 是否有值;而 orElseGet(Supplier extends T> supplier) 只在 Optional 为 empty 时才调用 Supplier,实现真正的惰性求值。
这对降级逻辑至关重要——比如降级值需查本地缓存、读文件、调用轻量计算(如当前时间戳拼接)、甚至触发一次兜底 HTTP 请求,你不希望这些操作在配置正常时也被无谓执行。
典型场景:动态生成降级值
假设你从 Apollo 获取一个限流阈值 rate.limit,类型为 Integer,要求:
- 若 Apollo 有非空有效整数,则直接使用;
- 若为空、非数字、或未发布,则降级为「当前机器 CPU 核数 × 2」;
代码可这样写:
Integer rateLimit = Optional.ofNullable(apolloConfigService.getConfig().getProperty("rate.limit", String.class))
.filter(StringUtils::isNotBlank)
.map(Integer::parseInt)
.orElseGet(() -> Runtime.getRuntime().availableProcessors() * 2);
注意:整个链路使用 Optional 组合操作,orElseGet 内部只在真正缺失时才调用 availableProcessors(),避免干扰正常路径。
结合 Apollo 的 ConfigChangeListener 实现热更新降级逻辑
降级值本身也可以是动态的。例如,你想在 Apollo 配置失效时,临时启用“按小时轮换”的降级策略(如每小时返回不同默认值):
private final Clock clock = Clock.systemUTC();
<p>// 在监听器中刷新或复用该逻辑
Integer fallbackRate = Optional.ofNullable(apolloConfigService.getConfig().getProperty("rate.limit", String.class))
.filter(StringUtils::isNotBlank)
.map(Integer::parseInt)
.orElseGet(() -> {
int hour = LocalDateTime.now(clock).getHour();
return switch (hour % 3) {
case 0 -> 100;
case 1 -> 200;
default -> 50;
};
});</p>这种写法让降级行为具备时间维度的适应性,且仍保持单次计算、按需触发。
避坑提醒:不要在 orElseGet 里做重操作
虽然 orElseGet 是惰性的,但它运行在配置读取线程(通常是业务线程或 Apollo 的回调线程)中。以下操作应避免:
- 同步远程调用(如 HTTP、DB 查询)——会阻塞配置获取,拖慢整个请求;
- 加锁或长耗时计算(如解析大 JSON、正则全量匹配);
- 修改共享状态(如 static 计数器),除非线程安全已保障。
如必须远程兜底,建议改用异步预热 + 本地缓存(如 Caffeine),再在 orElseGet 中读缓存。










