Java运行时异常(如NullPointerException)本质是程序BUG,应优先预防而非捕获;仅在外部输入校验、第三方SDK明确要求或顶层统一兜底时才用try-catch,且需具体捕获、记录日志,避免空catch或捕获Exception/Throwable。

Java 异常处理机制捕获和处理运行时错误,核心不是“把所有异常都 catch 住”,而是分清哪些该捕、哪些该改、哪些该放——尤其对运行时错误(即 RuntimeException 及其子类)。
运行时错误的特点与处理原则
运行时错误属于非受检异常(Unchecked Exception),编译器不强制要求处理。它们通常反映程序逻辑缺陷,比如:
- NullPointerException:对象为 null 却调用了方法或访问了字段
- ArrayIndexOutOfBoundsException:数组下标超出合法范围
- ArithmeticException:如除零操作
- IllegalArgumentException:传入非法参数(如负数作为数组长度)
这类异常的本质是BUG,不是意外场景。因此首要策略是预防,而非兜底捕获。
什么时候该用 try-catch 捕获运行时错误?
绝大多数情况下,不建议为 NullPointerException 或 ArrayIndexOutOfBoundsException 写通用 catch 块。但以下情况例外:
立即学习“Java免费学习笔记(深入)”;
- 边界明确的外部输入校验失败:比如解析用户提交的 JSON 字符串,用 Jackson 反序列化时可能抛出 JsonProcessingException(虽属受检异常),但若因字段类型错配引发 IllegalArgumentException,可针对性捕获并返回友好提示
- 第三方 SDK 内部抛出的运行时异常且文档明确说明需处理:例如某些老版本数据库驱动在连接中断时抛出 RuntimeException,而你无法升级依赖
- 统一兜底日志+降级(仅限顶层):如 Spring MVC 的 @ControllerAdvice 中捕获 RuntimeException,记录完整堆栈、返回 500 页面或默认响应,防止暴露敏感信息
更推荐的处理方式:主动防御,而非被动捕获
比起 try-catch,对运行时错误更有效、更可持续的做法是:
- 加空值检查:使用 Objects.requireNonNull(obj, "xxx must not be null") 主动失败,比静默 NPE 更早暴露问题
- 用 Optional 封装可能为空的返回值:避免调用方忘记判空
- 参数校验前置:方法入口用 Assert.notNull() 或 Jakarta Validation 注解(@NotNull)校验
- 集合操作用安全方法:如 List.get(i) 前先 check i < list.size();或改用 list.stream().skip(n).findFirst()
try-catch 写法要注意的关键细节
如果确实需要捕获,务必注意:
- 不要 catch Exception 或 Throwable:会吞掉 Error(如 OutOfMemoryError)和本不该捕获的严重问题
- catch 要具体,按从子类到父类顺序排列:例如先 catch NumberFormatException,再 catch IllegalArgumentException
- 不要空 catch:至少记录日志(用 log.error("msg", e)),否则异常彻底消失,排查无从下手
- 不要在 finally 里 return 或 throw:会覆盖 try/catch 中的返回值或异常,导致逻辑失控


















