java多catch块必须子类在前、父类在后,否则编译失败;因jvm从上到下匹配,父类若在前会提前捕获所有子类异常,导致后续catch不可达并报错“exception xxx has already been caught”。

多个catch块必须按子类异常在前、父类异常在后排列,否则编译直接失败——这不是风格建议,而是Java强制的语法约束。
为什么顺序不能错
Java虚拟机从上到下逐个检查catch块。只要抛出的异常对象是某个catch参数类型的实例或其子类,就立即进入该块执行,后续catch不再尝试匹配。如果Exception写在IOException前面,所有IOException实例都会被Exception捕获,后面的IOException catch块就成了不可达代码,编译器会报错:“exception IOException has already been caught” 或 “Unreachable catch block”。
正确排列的核心原则
- 最具体的异常(继承链最末端)放最上面,比如FileNotFoundException、SQLException、NumberFormatException
- 中间层级的父类依次向下排,比如IOException、IllegalArgumentException、RuntimeException
- 兜底的宽泛异常(如Exception、Throwable)必须放在最后
- 无继承关系的异常(如IOException和SQLException)谁先谁后都合法,但建议按业务常见度或语义分组安排
多异常捕获(|语法)的使用边界
Java 7+支持一个catch块处理多种异常,例如catch (IOException | SQLException e),但有严格限制:
- 竖线分隔的每个异常类型之间不能存在继承关系,否则编译报错:“alternative exception types must be disjoint”
- 变量e的静态类型是这些异常的最近公共父类(如Exception),不能直接调用子类特有方法,需配合instanceof判断后转型
- 不推荐把IOException | FileNotFoundException这样写——后者是前者的子类,违反规则
实际编码中的实用建议
- 优先捕获业务自定义异常(如UserAlreadyExistsException),再处理标准受检异常,最后是非受检异常和兜底
- 避免把Exception放在第一个catch块——它会直接导致编译失败,而不是掩盖问题
- IDE(如IntelliJ)会在编辑时高亮非法顺序并提供自动修复,可当作实时校验工具
- 不确定继承关系时,用Ctrl+Click跳转到异常类定义,看它extends谁,快速理清层级
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











