java要求catch块按“从具体到宽泛”顺序排列,否则编译报错;同级异常顺序可互换;多异常捕获(|语法)要求类型无继承关系;变量e类型为最近公共父类;推荐按业务语义分层处理异常。

子类异常被父类遮蔽,根本原因是 catch 块顺序写反了——父类写在前面,直接“拦下”所有子类异常,导致后续 catch 永远不执行。这不是运行时隐患,而是编译器立刻报错的硬性约束。
必须按“从具体到宽泛”排列
Java 要求每个 catch 块的异常类型,必须按继承关系由窄到宽书写。编译器会静态检查:如果某个 catch 的异常类型是之前 catch 类型的子类或相同类型,就判定为不可达,直接拒绝编译。
- ✅ 正确顺序:FileNotFoundException → IOException → Exception
- ❌ 错误顺序:Exception → IOException → FileNotFoundException(编译失败)
- 同级异常(如 IOException 和 SQLException)无继承关系,顺序可互换,但建议按业务常见度排
多异常捕获(|语法)也有同样限制
Java 7+ 支持一个 catch 处理多个异常,例如 catch (IOException | SQLException e),但前提是这些异常类型之间不能有继承关系。
- ✅ 合法:IOException 和 SQLException(都继承 Exception,但彼此无关)
- ❌ 非法:IOException | FileNotFoundException(后者是前者子类)
- 变量
e的类型是这些异常的最近公共父类(如 Exception),不能直接调用子类特有方法
实际编写中的分层建议
不是堆砌所有异常,而是按业务语义分层处理,既清晰又安全:
- 最上层:自定义业务异常(如 UserNotFoundException、OrderInvalidException)
- 中间层:标准受检异常(如 SQLException、IOException)
- 底层:非受检异常中需干预的(如 IllegalArgumentException、NullPointerException)
- 兜底层:Exception(仅限统一日志、包装再抛,不建议空 catch 或吞异常)
快速自查与 IDE 辅助
不用死记继承树,动手就能验证:
- 在 IDE 中 Ctrl+Click 点进异常类,看它 extends 谁,理清层级
- IntelliJ 或 Eclipse 会实时高亮非法顺序,并提供一键修复(如 “Reorder catch clauses”)
- 写完多 catch 后,删掉某个块,观察是否触发编译错误——若没报错,说明它原本就是不可达的
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











