异常链是错误接力赛,通过throw抛出、throws声明、catch捕获并可包装再抛出,需用带cause构造器保留原始异常信息,否则丢失调用链;主线程为终点,未捕获则程序终止。
可以把异常链理解成一场“错误接力赛”:谁出错了,就立刻把一根虚拟的接力棒(也就是异常对象)传给上一层处理者;如果上一层不接住、也不自己跑完,就继续往上传——直到有人真正停下来处理它,或者一路传到最外层没人接,程序才“摔倒终止”。
接力棒不是随便扔,得有明确交接动作
Java里这根接力棒的传递,靠的是 throw 和 throws 这两个关键词:
- throw new XxxException(...) 是“我摔倒了,现在把棒子交出去”——主动抛出一个新异常
- catch 块里再 throw e 或 throw new YyyException("...", e),就是“我接住了棒子,但自己跑不动,要么原样传上去,要么包一层再传”
- 方法声明 throws Exception 相当于提前喊话:“我可能接不住棒子,你们调用我的人请准备好接!”
包一层再传,才能看清来龙去脉
新手常犯的错是 catch 之后只写 throw new RuntimeException("出错了") ——这就等于把原来的接力棒丢了,换了一根没写名字的新棒子。别人根本不知道最初在哪跌倒、中间谁碰过。
正确做法是用带 cause 的构造器,比如:
throw new ServiceException("订单创建失败", originalException);这样异常打印出来,就会清晰显示:
Caused by: SQLException: Connection refused
就像接力记录本上写着:第3棒(Service)摔了,是因为第2棒(DAO)在跨栏时被第1棒(Driver)绊倒的。
主线程是终点裁判,没人接棒就直接判失败
main 方法没有被任何人调用,它是整个接力赛的终点线。如果异常一路传到这里还没被 try-catch 接住,JVM 就会打印堆栈并停止程序——相当于选手冲线前脱手掉棒,比赛终止。
所以不是“异常一定要被 catch”,而是“异常必须有人负责到底”:可以是某层用 try-catch 处理掉,也可以是向上声明 throws,让调用方承担这个责任。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











