编译器强制要求异常捕获按继承链从子类到父类排列:先filenotfoundexception再ioexception最后exception;多异常捕获(|)类型间不可存在继承关系;兜底catch(exception e)必须置于最后且慎用。

直接把子类异常写在父类异常前面,编译错误立刻消失。这不是运行时问题,而是编译器强制要求的静态检查规则。
按继承链从叶子到根排列
异常是类,有明确的父子关系。越靠近继承链末端的类越具体,必须优先声明:
- 先写 FileNotFoundException(
IOException的子类) - 再写 IOException(
Exception的子类) - 最后才写 Exception(顶层受检异常父类)
同理:NumberFormatException → IllegalArgumentException → RuntimeException → Exception。
并列异常顺序可互换,但建议分组
没有继承关系的异常,比如 SQLException 和 IOException,谁前谁后都合法。但实际编码中建议按语义或业务场景归类:
- 数据库相关:SQLException、SQLTimeoutException(注意后者是前者子类,必须靠前)
- IO 相关:FileNotFoundException、SocketTimeoutException、IOException
- 参数校验:IllegalArgumentException、IllegalStateException
多异常捕获(|)要避开继承陷阱
Java 7+ 支持一个 catch 处理多个类型,但竖线分隔的类型之间不能有继承关系:
- ✅
catch (IOException | SQLException e)—— 合法,二者同级 - ❌
catch (IOException | FileNotFoundException e)—— 编译报错,后者是前者子类
合并后变量 e 的类型是最近公共父类(通常是 Exception),若需调用子类特有方法,得先用 instanceof 判断再转型。
兜底异常必须放最后,且慎用
catch (Exception e) 或 catch (Throwable t) 不是不能写,而是绝不能放在任何具体异常之前:
- 放在最前会导致所有子类 catch 块不可达,编译失败
- 放在最后仅适合统一日志、包装重抛等收口逻辑,不建议静默吞掉异常
- 避免用
Throwable或Error捕获,它们不属于业务处理范畴
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











