多catch块须按继承层级从子类到父类排列,否则编译报错;可使用|并列无继承关系的异常;应优先捕获业务自定义异常,避免泛化catch(exception);资源清理首选try-with-resources。

多catch块的顺序必须严格遵循继承层级
Java在匹配异常时,是从上到下逐个检查catch块的。只要抛出的异常类型与某个catch声明的类型兼容(包括其子类),就立即进入该分支,后续catch全部跳过。所以子类异常必须写在父类前面,否则编译直接报错“unreachable catch block”。比如FileNotFoundException是IOException的子类,就必须先捕获前者,再捕获后者;而IOException和SQLException没有继承关系,谁先谁后都合法,但建议按业务发生频率或语义分组排列。
合理使用Java 7+的多异常捕获语法
当几种异常需要完全一致的处理逻辑(如统一记录日志、返回相同错误码),可用竖线(|)在一个catch中并列声明:
- ✅ 合法写法:
catch (IOException | SQLException e)—— 二者同属Exception子类,但彼此独立 - ❌ 非法写法:
catch (Exception | RuntimeException e)或catch (IOException | FileNotFoundException e)—— 存在继承关系,编译失败 - ⚠️ 注意:变量
e的静态类型是这些异常的最近公共父类(通常是Exception),不能直接调用子类特有方法;如需区分,得配合instanceof判断后转型
优先捕获业务语义化异常,避免泛化兜底
不要依赖catch (Exception e)应付一切。它会吞掉本该暴露的细节,让调试困难、监控失效。推荐做法是:
- 针对关键业务环节定义自定义异常,如
InsufficientStockException、InvalidCouponException - 在catch中包装上下文信息再抛出,例如:
throw new PaymentFailedException("余额不足", orderId, userId) - 除非是顶层入口(如main方法或全局异常处理器),否则不建议加
catch (Exception e)兜底;若必须加,至少完整打印堆栈,而非只取getMessage()
资源清理不能依赖catch块顺序
多个catch只是响应异常的入口,不是资源释放的终点。真正可靠的清理方式是:
- 优先使用
try-with-resources自动关闭流、连接等可关闭资源,比手动finally更简洁可靠 - 若需在catch中做补偿操作(如事务回滚、发送告警),确保该操作本身不抛新异常,以免覆盖原始异常
- 慎用
finally中的return或throw,它会遮蔽try或catch中已抛出的异常
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











