java中多个catch块必须按子类在前、父类在后的顺序排列,否则编译失败;并列异常无继承关系可任意排序;多异常捕获(|)要求类型互斥;兜底异常须置于最后。

Java中多个catch块的顺序直接决定哪些异常能被真正捕获,顺序写错会导致部分catch永远不执行——这不是运行时隐患,而是编译器直接拒绝的硬性规则。
子类异常必须排在父类前面
JVM按代码从上到下的顺序逐个比对catch参数类型。只要抛出的异常是某个catch参数类型的实例或其子类,就进入该块,后续catch不再检查。
- 比如IOException是Exception的子类,若把Exception写在前面,所有IOException都会被它“吃掉”,后面的IOException catch块编译不过,报错“Unreachable catch block”
- 同理,NullPointerException必须写在RuntimeException之前;FileNotFoundException必须写在IOException之前
- 这个规则适用于所有继承关系:自定义异常继承了RuntimeException,就得放在它前面
并列异常顺序可自由调整
没有继承关系的异常类型(如IOException和SQLException)互不干扰,谁先谁后不影响编译和执行。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 但建议按业务逻辑组织:高频异常放前(如数据库操作失败),低频或系统级异常放后(如网络超时)
- 避免把IllegalArgumentException和IllegalStateException这类语义接近的异常隔太远,方便维护
- 不要因为“看起来顺眼”就把SQLException故意挪到IOException下面——只要没继承关系,就安全
多异常捕获(|语法)也有继承限制
Java 7+支持用竖线合并多个异常类型,但前提是它们彼此独立,不能有父子关系。
- ✅ 合法:
catch (IOException | SQLException e)—— 二者都继承自Exception,但互不继承 - ❌ 非法:
catch (IOException | FileNotFoundException e)—— 编译报错“alternative exception types must be disjoint” - 合并后的变量e静态类型是这些异常的最近公共父类(通常是Exception),调用子类特有方法前需先instanceof判断再转型
兜底异常要慎用,且必须放最后
用Exception或Throwable做兜底本身没问题,但位置和意图必须清晰。
- 它只能出现在所有具体异常之后,否则会提前拦截,导致编译失败
- 不要把它当“保险丝”加在最前面——那样等于放弃异常分类处理,日志难排查,重试逻辑失效
- 真要兜底,至少记录完整堆栈:
log.error("Unexpected error", e);,而不是只打e.getMessage() - Error(如OutOfMemoryError)通常不应捕获,留给JVM处理更稳妥
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










