orElseGet仅在Optional为空时才延迟调用Supplier获取默认值,而orElse无论是否为空都会立即执行参数求值;前者适用于高成本、有副作用的默认值生成,后者仅适合轻量常量。

orElseGet 是 Optional 中用于安全获取值的方法之一,它和 orElse 类似,但关键区别在于:当 Optional 为空(isEmpty() 为 true)时,orElseGet **不会立即执行**传入的 Supplier,而是**延迟调用**——仅在需要时才生成默认值。这在默认值创建开销大、有副作用(如 IO、数据库查询、随机数生成等)时非常有用。
orElseGet 的基本用法
它接收一个 Supplier<T> 参数,返回类型与 Optional 的泛型一致:
Optional<String> opt = Optional.empty(); String result = opt.orElseGet(() -> "default"); // 返回 "default"
如果 Optional 非空,则直接返回其封装的值,Supplier 根本不执行;只有为空时,才会调用 Supplier 获取默认值。
为什么不用 orElse?
orElse(T other) 接收的是一个**已计算好的值**,无论 Optional 是否为空,该参数都会被提前求值。例如:
立即学习“Java免费学习笔记(深入)”;
-
opt.orElse(expensiveMethod())→expensiveMethod()总是被执行 -
opt.orElseGet(() -> expensiveMethod())→expensiveMethod()只在opt为空时才调用
这是两者最核心的性能与语义差异。
实用场景示例
常见于需要按需构造默认对象的场合:
-
从缓存读取用户,未命中时查库:
Optional<User> cached = cache.get(userId);<br> User user = cached.orElseGet(() -> userDao.findById(userId));
-
生成唯一 ID 或时间戳作为默认值:
Optional<String> id = getIdFromRequest();<br> String finalId = id.orElseGet(() -> UUID.randomUUID().toString());
-
避免空集合导致 NPE,提供新 ArrayList:
Optional<List<Item>> items = parseItems(json);<br> List<Item> list = items.orElseGet(ArrayList::new);
注意事项
Supplier 必须是非 null 的函数式接口实例,否则会抛出 NullPointerException;同时,Supplier 内部逻辑应尽量保持无状态、线程安全(尤其在并发环境中使用)。
如果 Supplier 抛出异常,该异常会原样向上抛出,orElseGet 不做捕获或包装。


















