应继承Exception当调用方必须显式处理业务异常(如支付超限、库存不足),编译器强制捕获;继承RuntimeException适用于程序缺陷类错误(如空参、状态不一致),便于快速暴露问题;需提供标准构造函数并规范命名。

选继承 Exception 还是 RuntimeException,关键看调用方有没有能力、责任或必要去主动应对这个错误。
该继承Exception的情况
适用于调用方必须显式处理的业务异常,比如重试、降级、提示用户或走补偿流程。编译器会强制要求 try-catch 或 throws,避免被忽略。
- 支付金额超限、库存不足、订单已发货等明确可预判、有业务含义的失败
- 外部依赖返回明确错误码(如 HTTP 401、SQL 语法错误)且上层需定制响应
- 第三方服务不稳定,你希望调用方“不得不”考虑熔断或备用方案
该继承RuntimeException的情况
适用于程序逻辑缺陷、参数校验失败、配置缺失等本不该发生、或发生后无法合理恢复的问题。编译器不干预,便于快速暴露问题。
- 传入 null 参数且契约不允许(如
OrderService.create(null)) - 状态不一致(如“订单已完成却尝试取消”)
- 配置项为空、JSON 解析失败等开发阶段应拦截的错误
命名和构造函数要规范
不管选哪个父类,都必须提供标准构造函数:
MyException()MyException(String message)MyException(String message, Throwable cause)
不要覆盖 getMessage() 或 getCause();命名体现业务语义(如 InsufficientBalanceException),而非技术细节(如 CheckFailedException)。
别踩这些坑
- 直接继承
Throwable或Object:编译失败,JVM 不识别 - 把本该由调用方响应的错误设为
RuntimeException:重试、降级逻辑容易被跳过 - 给
RuntimeException子类加throws声明:无实际作用,反而干扰阅读和静态检查 - 用
new Exception("xxx")代替自定义类:丢失业务语义,无法精准捕获

















