runtimeexception 是非检查异常,用于表达程序逻辑错误,如空指针、非法参数等,应通过修复代码而非捕获来解决;推荐使用其具体子类并提供有意义的提示信息。

RuntimeException 是什么,什么时候该用它
RuntimeException 是 Exception 的子类,但属于“非检查异常”(unchecked exception)。Java 编译器不强制要求你 try-catch 或 throws 它——也就是说,代码里抛出 RuntimeException 不会编译报错。
它适合表达**程序逻辑错误**,比如空指针、数组越界、类型转换失败、非法参数等。这类问题通常不该靠外部调用者来“兜底”,而应通过修复代码逻辑来避免。
- 不要用
RuntimeException替代业务校验失败(比如“余额不足”该抛自定义BusinessException) - 不要在 catch 里吞掉
RuntimeException后静默返回(容易掩盖 bug) - 框架如 Spring 默认把未捕获的
RuntimeException转为 HTTP 500,这点要心里有数
怎么抛一个有意义的 RuntimeException
直接 new 一个 RuntimeException 并不推荐——信息太泛。优先用它的子类,或传入带上下文的 message。
if (userId == null) {
throw new IllegalArgumentException("userId must not be null");
}
if (list == null || list.isEmpty()) {
throw new IllegalStateException("order list is uninitialized or empty");
}
常见子类别乱选:
立即学习“Java免费学习笔记(深入)”;
-
NullPointerException:只在明确是解引用 null 时由 JVM 抛,自己别手动 throw -
IllegalArgumentException:参数值非法(如负数传给“数量”字段) -
IllegalStateException:对象状态不满足操作前提(如连接已关闭却还要 send 数据) -
UnsupportedOperationException:集合实现类中未支持某操作(如unmodifiableList的add())
捕获 RuntimeException 要不要做?
绝大多数情况下——不要专门 catch RuntimeException。它代表程序缺陷,修复代码比写 try-catch 更治本。
例外场景极少,比如:
- 顶层异常处理器(Spring 的
@ControllerAdvice)统一记录日志并转成友好响应 - 集成不可控第三方 SDK,它内部疯狂 throw
RuntimeException且文档不清,你只能兜底 - 批处理任务中单条数据出错不能阻断整体流程,需 catch 后标记失败并继续
若真要 catch,请限定具体子类,而非笼统 catch RuntimeException:
try {
processOrder(order);
} catch (IllegalArgumentException e) {
log.warn("Invalid order data: {}", order.getId(), e);
markAsInvalid(order);
}
自定义 RuntimeException 的正确姿势
业务中需要区分异常语义时,继承 RuntimeException 即可,无需重写太多东西。重点是构造函数和序列化安全。
public class InsufficientBalanceException extends RuntimeException {
private final String accountId;
public InsufficientBalanceException(String accountId, BigDecimal required) {
super(String.format("Account %s has insufficient balance for %.2f", accountId, required));
this.accountId = accountId;
}
// 保证反序列化时能重建字段(如果走网络或持久化)
protected InsufficientBalanceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
this.accountId = null;
}
}
注意点:
- 除非明确需要,否则别加 checked exception 的
throws声明 - 避免在构造函数里做耗时操作(如查 DB、远程调用)
- message 里别拼接敏感数据(如密码、token),日志可能泄露
真正难的不是抛异常,而是判断哪一层该抛、哪一层该转、哪一层该沉默——这些没标准答案,得看调用边界和监控能力。








