java多catch块按继承关系和声明顺序匹配,子类异常必须写在父类前面,否则编译失败;无关异常顺序可调;多异常捕获要求类型无继承关系;兜底异常须置于最后。

Java多catch块不是按“谁先写谁先执行”来机械匹配,而是严格依赖异常类之间的继承关系和声明顺序。子类异常必须写在父类前面,否则编译直接失败——这不是运行时逻辑问题,而是编译器主动拦截无效代码。
子类异常必须排在父类前面
编译器从上到下扫描catch块,一旦某个catch参数类型能匹配抛出的异常(即该异常是其声明类型的实例或子类),就立即进入该块,后续catch全部跳过。如果父类写在前面,比如Exception放在IOException之前,那么所有IOException及其子类(如FileNotFoundException)都会被Exception捕获,后面的catch永远不可达。
-
FileNotFoundException是IOException的子类,必须写在IOException之前 -
NullPointerException是RuntimeException的子类,也必须写在它前面 - 编译报错信息通常是:
exception XXX has already been caught
并列无关异常顺序可灵活调整
没有继承关系的异常类,比如SQLException和IOException,它们都继承自Exception但互不隶属,这种情况下多个catch块的顺序不影响编译,也不影响运行时匹配结果。
- 可以按业务场景分组:数据库异常放一起,文件操作异常放一起
- 也可以按发生频率排序:常见异常靠前,便于快速定位问题
- 但不能把
SQLException和它的子类SQLTimeoutException混排,后者必须在前者之前
多异常捕获(|语法)有严格类型限制
Java 7起支持一个catch块捕获多种异常,写法是catch (IOException | SQLException e),但前提是这些类型之间不能存在继承关系。
- ✅ 合法:
IOException | SQLException(二者同级,最近公共父类是Exception) - ❌ 非法:
IOException | FileNotFoundException(后者是前者子类) - 变量
e的静态类型是所列异常的最小公共父类,无法直接调用子类特有方法,需先instanceof判断再转型
兜底异常要谨慎使用
用Exception或更宽泛的类型做兜底是常见做法,但它必须放在所有具体异常之后,否则会阻断后续catch;同时应避免使用Throwable或Error,它们不属于业务异常处理范畴。
-
catch (Exception e)适合收口,但不要掩盖真正需要区分处理的问题 - 日志记录、资源清理等通用逻辑,优先考虑
finally或try-with-resources,而不是依赖靠后的catch - IDE通常会提示“Catch clause order”,可作为检查顺序是否合理的辅助依据
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











