Java自定义异常需继承Exception(检查型,强制处理)或RuntimeException(非检查型,无需强制处理),并提供无参、String参数、String+Throwable参数构造方法,类名以Exception结尾,消息应具体可读,支持异常链和业务字段扩展。

在Java中自定义异常,核心是继承 Exception 或 RuntimeException 类,并提供合适的构造方法。是否需要检查(checked)取决于你继承的是哪个父类。
继承 Exception 实现检查型异常
这类异常必须在编译期处理(try-catch 或 throws),适合表示可预期、应主动恢复的业务问题,比如“余额不足”“用户名已存在”。
- 新建类,继承 Exception
- 至少提供两个构造方法:无参构造 + 带 String 参数的构造(调用 super(msg))
- 可选:增加带 Throwable cause 的构造,支持异常链
示例:
public class InsufficientBalanceException extends Exception {
public InsufficientBalanceException() {
super("账户余额不足");
}
public InsufficientBalanceException(String message) {
super(message);
}
public InsufficientBalanceException(String message, Throwable cause) {
super(message, cause);
}
}
继承 RuntimeException 实现非检查型异常
这类异常无需强制处理,适合表示程序逻辑错误或不可恢复的意外,比如“参数为空”“状态非法”。
立即学习“Java免费学习笔记(深入)”;
- 继承 RuntimeException,不是 Exception
- 同样建议提供常用构造方法(String、String+Throwable)
- 抛出时不用声明 throws,调用方更自由
示例:
public class InvalidStatusException extends RuntimeException {
public InvalidStatusException(String status) {
super("非法状态: " + status);
}
}
使用时注意的关键点
- 异常类名以 Exception 结尾,语义清晰(如 PaymentFailedException)
- 消息内容应具体、可读,避免空字符串或纯代码(如 "error 1001")
- 如果涉及业务上下文,可在异常类中添加字段(如 orderId、userId),并提供 getter
- 不要吞掉原始异常——用 cause 构造器保留堆栈,便于排查
什么时候该自定义,而不是直接 throw new RuntimeException?
- 需要区分异常类型做不同处理(比如对支付失败重试,对参数错误直接返回)
- 团队协作中统一错误码/日志格式,靠自定义类封装逻辑
- 框架(如 Spring)能基于异常类型自动映射 HTTP 状态码
- 想让调用方明确感知某类业务风险,而非笼统的运行时错误
基本上就这些。自定义异常不复杂但容易忽略语义和使用场景,关键是让异常真正“说话”。










