orelseget用于optional为空时延迟生成默认值,而orelse无论是否有值都会立即执行默认值构造,因此orelseget可避免不必要的计算开销,提升性能。

orElseGet 是 Java 8 引入的 Optional 类中的一个方法,专门用于在 Optional 为空(即 isPresent() == false)时,**延迟执行一段逻辑来生成默认值**,避免无谓的对象创建或计算。
为什么用 orElseGet 而不是 orElse?
关键区别在于执行时机和性能:
-
orElse(T other):**无论 Optional 是否有值,都会立即计算并传入默认值**(比如 new Object()、methodCall() 都会执行) -
orElseGet(Supplier extends T> supplier):**只在 Optional 为空时才调用 supplier.get()**,实现惰性求值
例如:
// ❌ 不推荐:即使 user.isPresent() 为 true,也会创建新 User 对象
User fallback = user.orElse(new User("guest", 0));
// ✅ 推荐:只有 user 为空时才创建
User fallback = user.orElseGet(() -> new User("guest", 0));
如何正确使用 orElseGet
传入一个 Supplier 函数式接口实例,通常用 Lambda 表达式或方法引用:
- 简单值:`() -> "default"`
- 带逻辑的默认值:`() -> fetchDefaultUserFromDB()`
- 复用已有方法:`User::newDefault`(前提是该方法符合 Supplier 签名)
示例:
Optional<string> name = Optional.empty();
String result = name.orElseGet(() -> {
System.out.println("正在生成默认名称...");
return "Anonymous";
});
// 输出:正在生成默认名称...
// result = "Anonymous"
</string>
常见误用和注意事项
注意以下几点,避免踩坑:
- Supplier 的返回类型必须与 Optional 的泛型类型一致(编译时检查)
- 不要在 supplier 中抛出受检异常(如 IOException),否则需包装成 RuntimeException 或改用 try-catch
- 避免在 supplier 中做耗时或副作用操作(如网络请求、数据库写入),除非你明确需要每次为空都触发
- 如果默认值是常量且无副作用,
orElse("xxx")更简洁;只有需要延迟/动态生成时才选orElseGet
对比 orElseThrow 的适用场景
orElseGet 和 orElseThrow 都是惰性求值,但目的不同:
-
orElseGet:补一个合理默认值,程序继续运行 -
orElseThrow:空值不可接受,主动抛异常中断流程
例如配置读取:
String timeout = config.get("timeout")
.map(Integer::parseInt)
.orElseGet(() -> {
log.warn("timeout not set, using default 3000ms");
return 3000;
});
不复杂但容易忽略——只要记住“要懒加载就用 orElseGet,要立刻给就用 orElse”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











