多 catch 块本身不破坏异常链,关键在于抛出方式和日志习惯;原样重抛或双参构造包装可保留堆栈,而单参 RuntimeException、finally 抛异常等操作会截断堆栈。
多 catch 块本身不破坏异常链,关键在于每个 catch 中怎么处理捕获到的异常。真正影响堆栈完整性的,是抛出方式和日志记录习惯,不是 catch 的数量或顺序。
多个 catch 块只是对同一异常做类型匹配,异常对象在 throw 时已生成完整堆栈,catch 只是“接住”,不会修改它。无论你写一个 catch 还是五个,只要没新建异常、没调用 setStackTrace() 或 initCause(),原始堆栈就原封不动。
根据是否需要语义转换,选择对应方式:
throw e;,不 new 新对象。方法签名需声明 throws,日志用 logger.error("操作失败", e)
throw new OrderException("下单失败", e);自定义异常类中必须调用 super(message, cause)
代码里链建对了,日志打错等于白干:
立即学习“Java免费学习笔记(深入)”;
logger.error("支付回调异常", ex) ✅,而不是 "支付回调异常: " + ex.getMessage() ❌%ex,Log4j2 用 %throwable{full}
ex.getCause(),尤其在 try-with-resources 场景下,原始异常可能藏在 ex.getSuppressed() 里这些操作表面像在处理异常,实则悄悄截断堆栈:
RuntimeException(e) 单参构造:e 被当 message 字符串处理,不是 cause,堆栈链断裂initCause():已被包装过的异常 cause 不为 null,再调直接抛 IllegalStateException
e.getMessage() 或 e.toString():完全看不到堆栈轨迹和嵌套关系