Optional 为空时应优先使用 orElseThrow() 配合 Supplier 抛出自定义 RuntimeException,动态拼接上下文信息;可封装为 requirePresent 工具方法提升复用性,避免 isPresent+get 或 empty().get() 等反模式。

Java 中 Optional 本身不支持直接抛异常,但可以通过 orElseThrow() 方法在值为空时触发自定义异常,并附带清晰提示信息,这是最常用且推荐的方式。
用 orElseThrow 配合 Lambda 抛出自定义异常
这是最简洁、语义最明确的做法。你可以传入一个 Supplier 异常构造器,在 Optional 为空时执行,动态生成带上下文的提示消息。
- 避免硬编码异常消息,把关键变量(如 ID、参数名)拼进提示中,便于排查
- 异常类型建议继承
RuntimeException(如IllegalArgumentException或自定义业务异常),无需强制 try-catch - 示例:
Long userId = 1001L;
User user = Optional.ofNullable(userRepository.findById(userId))
.orElseThrow(() -> new UserNotFoundException("用户不存在,ID=" + userId));
封装通用工具方法提升复用性
当多个地方需要类似逻辑(如“查不到就抛 XX 异常”),可抽成静态工具方法,减少重复代码和字符串拼接错误。
- 方法签名可设计为
<T> T requirePresent(Optional<T> opt, Supplier<RuntimeException> exceptionSupplier) - 调用时更聚焦业务意图:
requirePresent(userOpt, () -> new BizException("订单未找到")) - 也可进一步封装为带格式化能力的版本,比如支持
String.format风格的提示模板
避免常见误区
有些写法看似可行,实则破坏了 Optional 的初衷或引入隐患:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 不用
isPresent() + get()再手动 throw —— 多余且易出 NPE(若中间被修改) - 不要在
orElseThrow的 lambda 里做复杂逻辑(如远程调用、DB 查询)—— 违反“空值处理应轻量”原则 - 别用
Optional.empty().get()触发默认NoSuchElementException—— 提示太笼统,不利于定位问题
配合 Lombok 或 Spring 的小技巧
如果项目已用 Lombok,可借助 @NonNull + 构造器校验做前置防御;Spring 用户还可结合 @Valid 和 BindingResult 统一处理参数缺失类异常,与 Optional 场景互补。
关键是让异常消息说清楚「什么没找到」「依据是什么」「建议怎么做」,而不是只抛个空泛的“null”。

















