受检异常强制显式错误处理,需继承exception、类名不含“runtime”、提供两个构造函数,并在方法签名中throws声明,使编译器强制调用方处理;每种异常对应具体业务动作,辅以ci检查、统一基类和openapi文档保障实效。

用受检异常实现显式错误的强制处理,核心是让编译器成为“守门人”——不是靠约定、文档或人工提醒,而是让代码通不过编译,除非开发者明确回应了那个风险。
定义真正有效的受检异常类
光写个继承 Exception 的类还不够,必须满足三个硬性条件:
- 直接继承 Exception,不能是 RuntimeException 的任何后代(哪怕只隔一层也不行)
- 类名不含 “Runtime” 字样(例如
InsufficientBalanceException合法,RuntimeInsufficientBalanceException就会被编译器忽略) - 提供两个构造函数:
public XxxException(String message)和public XxxException(String message, Throwable cause),否则无法传递业务上下文或封装原始异常
在关键方法上显式声明 throws
定义好异常只是第一步。必须在真正存在外部不确定性的地方,把 throws 写进方法签名里:
- 比如库存扣减方法:
public Order deductStock(Order order) throws InsufficientStockException - 调用方一旦使用这个方法,IDE 或 javac 立刻报错:“unreported exception InsufficientStockException; must be caught or declared to be thrown”
- 没有 try-catch,也没有向上 throws?编译失败,没商量
让每个异常对应一个可操作的业务场景
避免泛化命名,每个异常类型都该回答一个问题:“遇到它,我具体该做什么?”
-
PaymentTimeoutException→ 前端提示“支付超时,请重试或换方式”,后端触发异步查单 -
ConcurrentInventoryUpdateException→ 自动重试 + 触发补偿校验,而非静默吞掉 -
RegulatoryRuleViolationException→ 阻断流程、记录审计日志、通知合规接口人
这样 catch 块就不再是形式主义,而是自然带出恢复逻辑。
配套机制防止绕过或弱化约束
编译器强制只是起点,还需工程手段加固效果:
- CI 流水线中加入检查:禁止
catch (Exception e) { }或仅调用e.printStackTrace() - 统一异常基类重写
getMessage(),自动附加建议动作,例如“请调用AccountService#refreshStatus()后重试” - OpenAPI 文档将这些受检异常列为 4xx 响应码,并注明触发条件和推荐处理路径











