orelsethrow用于optional为空时抛出指定异常,支持延迟创建、任意throwable类型及业务语义化异常,仅在空值时执行supplier,适用必须存在资源的场景。

orElseThrow 用于在 Optional 为空时立即抛出异常,而不是返回默认值。它让你能精准控制缺失数据的错误类型和提示信息,避免空指针或模糊异常。
orElseThrow 的基本用法
orElseThrow 接收一个 Supplier
- 写法简洁:Optional.ofNullable(user).orElseThrow(() -> new UserNotFoundException("用户ID为123不存在"))
- 延迟执行:lambda 中的异常对象只在需要时创建,避免无意义的实例化
- 类型自由:可抛出任意 Throwable 子类,不限于 RuntimeException
抛出自定义业务异常
建议封装具体业务含义的异常类,比如 UserNotFoundException、OrderExpiredException,让调用方能明确识别问题场景。
- 定义异常:public class UserNotFoundException extends RuntimeException { ... }
- 使用时传入带上下文的消息:orElseThrow(() -> new UserNotFoundException("查询用户失败,ID=" + userId))
- 配合日志或监控,消息中包含关键参数,便于排查
与 orElse 和 orElseGet 的区别
orElse 总是执行参数表达式,无论 Optional 是否为空;orElseGet 只在为空时执行 Supplier;orElseThrow 则只在为空时执行 Supplier 并抛异常。
- 错误写法(每次都创建异常):orElseThrow(new IllegalArgumentException("...")) —— 编译不通过,必须用 lambda
- 正确写法:orElseThrow(() -> new IllegalArgumentException("...")) —— 异常仅在空值时构建
- 对比 orElseGet:两者都延迟执行,但 orElseThrow 明确表达“缺失即错误”的语义
实际使用注意事项
不要为了用而用。只有当空值确实代表异常流程时才用 orElseThrow,否则可能掩盖正常空逻辑。
- 避免在 DAO 层盲目使用:如果数据库查不到用户是正常业务分支(如注册页查重),就不该抛异常
- 适合场景:API 必须存在某资源(如根据 token 查当前登录用户),空值意味着系统不一致或非法请求
- 异常消息尽量包含可追溯信息,如 ID、时间戳、来源模块,但避免泄露敏感数据
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











