面试题:自定义受检异常对调用者来说意味着什么

作者:袖梨 2026-07-08
自定义受检异常强制调用方显式处理,体现可恢复的业务语义而非技术错误;它明确契约、暴露风险、倒逼分层决策,但跨进程场景不适用且易被误用为形式主义。

自定义受检异常对调用者意味着:**必须显式处理,不能忽略**。

它强制调用方做决策

只要方法声明了 throws YourCheckedException,编译器就会要求调用方要么用 try-catch 捕获并响应,要么在自己方法签名中继续 throws。这不是建议,是编译期硬性约束。

  • 调用方无法“假装没看见”——不处理就编译失败
  • 这种强制力把业务风险提前暴露在接口契约里,比如“余额不足”不是隐藏逻辑,而是方法明确告诉调用方:“我可能抛这个,你得想好怎么回用户”
  • 它倒逼设计者思考:这个失败场景,调用方是否真有能力或职责去恢复?

它传递的是可恢复的业务语义,不是技术故障

受检异常不是用来表达空指针、数组越界这类编程错误,而是表达“业务上走到了另一条合法路径”。比如:

  • InsufficientBalanceException → 调用方可以引导用户充值或换支付方式
  • InvalidCouponStateException → 调用方可返回“该优惠券不可用”,无需重试或告警
  • CreditRejectedException → 上游服务可决定走人工审核,而不是直接失败

它隐含分层责任边界

谁该处理,不是由异常类型决定,而是由调用链中“第一个能做业务决策的位置”决定:

  • DAO 层抛出 ProductOutOfStockException,不代表它该在这里 try-catch —— 它只负责发现并声明问题
  • Controller 层捕获后返回 HTTP 400 + 友好提示,才是合理归宿;若 Service 层强行吞掉并返回 null,反而掩盖了业务意图
  • 全局 @ControllerAdvice 统一转 JSON 响应,是常见且合理的集中处理点,但前提是异常真正抵达了有业务上下文的位置

它容易被误用,导致负担大于价值

如果只是机械地 throws 向上传递,最终堆到顶层却没做任何用户反馈或降级动作,那这个异常就失去了意义:

  • 调用方被迫写一堆空 catch 或无脑包装成 RuntimeException,等于废掉了编译检查
  • 在 RPC、HTTP、消息队列等跨语言/跨进程场景中,受检异常类型无法传递,只剩 message 字符串,语义丢失
  • 现代 Web 开发中,绝大多数业务拒绝(如参数校验失败、状态不匹配)更适合用运行时异常 + 统一响应体,而非受检异常

相关文章

精彩推荐