题目重点:说明异常如何沿调用栈传播,何时捕获、重抛或转业务错误,并与崩溃和错误码区分。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 讨论支持 throw/try/catch/finally 的常见语言;受检异常、运行时异常和 panic/fatal error 的具体分类依语言而异。
解题路线
- 异常是普通返回值之外的控制流与错误信息传播机制:在某层 throw,运行时沿调用栈寻找匹配 handler;若无人处理,可能终止当前线程/请求/进程,取决于宿主。
- 在能作有意义恢复的边界捕获,例如网络超时可重试、用户输入可转 4xx;程序不变量破坏不应吞掉后假装成功。保留 cause/stack/context,让上层知道失败来源。
- 锁、文件和事务要用 finally/RAII/try-with-resources 等结构清理;捕获后重试必须有次数、退避和幂等保护。业务可预期失败也可建模为显式 Result/错误码,尤其在高频路径,选型由语言与团队契约决定。
- 不要把 exception 与进程崩溃画等号:某些异常被处理后请求可继续,严重 fatal error 或未捕获异常可能结束执行。日志只在负责处理的边界记录一次,避免逐层重复打同一错误。
手动走一遍
服务请求下游 API 超时:客户端抛 Timeout,服务层在 deadline 内最多重试一次,仍失败则返回明确错误并保持原 cause;finally 释放连接。若捕获后返回空结果,会把故障误当没有数据。
规模与取舍
异常机制不是单一算法;抛出/栈展开成本依语言与栈深度,不能无证据给固定 O(1) 或毫秒值。正确性取决于恢复边界、资源释放和错误可观察性。
易错点与追问
容易失分的边界
- `catch(Exception)` 后静默继续。
- 同一异常每层都记录完整堆栈,日志放大。
- 重试无幂等/退避导致副作用重复。
- 把业务无结果当异常或把系统异常当无结果。
- 异常路径忘关资源/回滚事务。
继续深挖
- 应在哪一层 catch?
- 异常与 Result 类型怎么选?
- 重试怎样避免重复扣款?
- finally 自己抛错时原异常怎么办?
