运行时异常不强制捕获但必须合理处理:禁用空catch、避免泛化捕获Exception、不用异常作控制流、优先用Optional和断言主动防御。

运行时异常(RuntimeException)本身不强制要求捕获,但“不捕获”不等于“不处理”。捕获不当——比如空 catch、泛化捕获、掩盖问题本质——反而会让 Bug 更隐蔽、更难定位。改的关键不是多加 try-catch,而是让异常暴露得更早、含义更清晰、修复更有依据。
别用空 catch 吞掉异常
空 catch 块是最大隐患之一:它让程序看似正常运行,实则跳过关键错误路径,后续逻辑可能基于错误状态继续执行,最终结果错得离谱却无迹可寻。
- ❌ 错误写法:
catch (NullPointerException e) { }(什么也不做) - ✅ 正确做法:至少记录日志,并保留原始堆栈
catch (NullPointerException e) {<br> logger.error("用户信息为空导致头像加载失败", e);<br> throw new ServiceException("头像服务不可用,请稍后重试");<br>}
避免用 Exception 大而化之去捕获
用 catch (Exception e) 捕获所有异常,会把本该由不同逻辑处理的 NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException 全混在一起,失去语义区分,也容易漏掉本该提前预防的问题。
- ✅ 分层捕获:先 catch 具体类型,再考虑兜底
try {<br> processOrder(orderId);<br>} catch (IllegalArgumentException e) {<br> // 参数校验失败,直接返回提示<br> return Response.fail("订单ID格式错误");<br>} catch (NullPointerException e) {<br> // 这属于代码缺陷,应修复而非掩盖<br> logger.warn("订单对象未初始化,触发NPE", e);<br> throw new IllegalStateException(e);<br>}
别在业务流程里靠异常做控制流
把异常当 if 用,比如靠 NumberFormatException 判断字符串是否为数字,或靠 ClassCastException 区分消息类型——这违反异常设计初衷,性能差、可读性低、难以维护。
立即学习“Java免费学习笔记(深入)”;
- ✅ 改成显式判断:
- 用StringUtils.isNumeric(str)或正则预检数字格式;
- 用instanceof+ 类型分支替代强制转型后捕获异常;
- 对可预期的边界情况(如空集合、默认值),用条件语句处理,而非等待抛异常再 catch。
用 Optional 和断言主动防御
很多运行时异常源于“假设对象非空”“假设参数合法”,但没验证。与其等崩溃再修,不如在入口就堵住。
- 对可能为空的返回值,用
Optional<t></t>明确表达不确定性,调用方必须显式处理 empty 场景; - 方法内部用
Objects.requireNonNull(obj, "user must not be null")或自定义校验工具,在出错第一时间抛出带上下文的IllegalArgumentException; - 单元测试中覆盖 null/越界/非法参数等用例,让这类 Bug 在开发阶段就浮现。


















