orElseThrow是Optional用于空值兜底抛异常的方法,支持默认NoSuchElementException或自定义异常;推荐使用Supplier版本延迟创建异常,适用于参数校验、配置读取等严格场景。

orElseThrow 是 Optional 提供的用于“空值兜底处理”的方法,当 Optional 为 empty() 时,它会立即抛出你指定的异常,而不是返回默认值。这特别适合对缺失数据采取严格校验策略的场景,比如参数校验、配置读取、数据库查询结果必存在等。
orElseThrow 的基本用法
它有两种重载形式:
-
orElseThrow():抛出默认的NoSuchElementException -
orElseThrow(Supplier<? extends Throwable>):传入一个异常构造器(Lambda 或方法引用),按需创建并抛出任意受检/非受检异常
推荐始终使用带 Supplier 的版本,便于自定义异常类型和提示信息。
抛出自定义异常(推荐写法)
例如查询用户失败时抛出业务异常:
立即学习“Java免费学习笔记(深入)”;
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("用户 ID " + userId + " 不存在"));
注意:Lambda 中的异常构造是延迟执行的——只有 Optional 为空时才真正调用,避免无谓的对象创建。
配合受检异常使用
如果要抛出受检异常(如 IOException),必须确保所在方法声明了该异常或用 try-catch 包裹:
String configValue = configService.get("timeout")
.map(String::trim)
.filter(s -> !s.isEmpty())
.orElseThrow(() -> new IOException("配置项 'timeout' 缺失或为空"));
此时方法签名需加上 throws IOException,否则编译不通过。
替代 ifPresentOrElse 的严格校验场景
当你**不需要默认值,只关心“必须有值”**,就别用 orElse(null) 或 get()(易 NPE),直接用 orElseThrow 更清晰、更安全:
- ❌
user.get()—— 空时抛NoSuchElementException,但异常信息不明确 - ❌
user.orElse(null)—— 把空转成null,后续可能引发 NPE - ✅
user.orElseThrow(() -> new IllegalArgumentException("用户信息不能为空"))—— 意图明确,异常可读性强
不复杂但容易忽略。


















