Java处理运行时异常的核心目标是不崩溃、不中断主流程、给出合理响应;应优先预防、精准捕获、兜底恢复,并可自定义异常增强业务语义。

Java 中处理运行时异常(如 NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException)的核心目标不是“完全阻止异常发生”,而是让程序在异常出现时**不崩溃、不中断主流程、给出合理响应**。运行时异常属于 RuntimeException 及其子类,编译器不强制捕获,但放任不管极易导致程序意外终止或逻辑错乱。
优先预防:用校验代替被动捕获
多数运行时异常源于可预知的非法状态,提前检查比事后捕获更高效、更清晰:
- 对可能为
null的对象,用Objects.nonNull()或Optional判断后再调用方法 - 访问数组或集合前,先检查索引是否在
[0, size)范围内 - 做除法前判断除数是否为 0;解析数字前用正则或
tryParse风格逻辑(如Integer.valueOf(str)前先str.matches("-?\d+")) - 方法入参用
@NonNull注解 + 构造时校验,把问题拦截在入口
精准捕获:只 catch 真正需要干预的异常
不要用 catch (Exception e) 一锅端,这会掩盖真正的问题,也违背“最小捕获原则”:
- 明确知道某段代码可能抛出哪种异常(例如
Integer.parseInt()抛NumberFormatException),就只捕获它 - 一个
try块后可跟多个catch,按子类到父类顺序排列(如先NumberFormatException,再IllegalArgumentException) - 捕获后不做任何处理(即空
catch)是严重反模式;至少要记录日志、返回默认值或抛出带上下文的业务异常
兜底与恢复:保障关键路径不中断
对无法完全预防、又必须继续执行的场景,用结构化方式隔离风险:
立即学习“Java免费学习笔记(深入)”;
- 在
catch块中提供安全的默认行为(如返回空集合、-1、空字符串),而不是让调用方收到null - 涉及资源操作(如文件、流、连接)时,即使处理运行时异常,也要确保清理——用
try-with-resources(自动关闭)或finally块释放 - 对外暴露的 API 方法,可在最外层加一层通用异常处理器(如 Spring 的
@ControllerAdvice),统一转换为友好的错误响应,避免堆栈信息泄露给用户
增强语义:用自定义运行时异常表达业务意图
当标准异常类型无法准确描述业务问题时,继承 RuntimeException 创建专属异常:
- 比如订单服务中,“库存不足”不应抛
IllegalStateException,而应抛InsufficientStockException - 自定义异常可携带订单号、商品ID等上下文字段,便于排查和监控
- 这类异常仍属非受检异常,调用方无需强制处理,但团队约定在关键节点捕获并记录


















