Java 7+ 多重捕获需用圆括号包裹互不继承的异常类型,如 catch (IOException | SQLException e),e 的静态类型为其最近公共父类(如 Exception),且仅适用于处理逻辑完全一致的场景。

Java 7+ 多重捕获 catch 语法怎么写才不报错
多重捕获只允许在同一个 catch 块中用 | 分隔多个**互不继承**的异常类型,且不能重复或包含父类。写错最常见的报错是 Alternatives in a multi-catch must be disjoint —— 比如同时写 IOException | Exception,因为后者是前者的父类。
- 必须用圆括号包裹多个异常类型:
catch (IOException | SQLException e) - 所有异常类型必须是 final 或不可被继承的(比如
Exception不行,IOException和SQLException可以) -
e的静态类型是这些异常的**最近公共父类**(通常是Exception),所以不能直接调用子类特有方法 - 如果需要区分处理,得用
instanceof手动判断,但这就失去多重捕获的简洁意义了
什么时候该用多重捕获,而不是多个 catch 块
核心判断标准:**异常处理逻辑完全一致**。比如都只是记录日志 + 统一返回错误码,那一个 catch 块更干净;如果要分别关闭不同资源、或抛出不同业务异常,就老老实实用多个 catch。
- 典型场景:JDBC 操作中同时捕获
SQLException和SQLTimeoutException(后者是前者的子类,但 JDK 8+ 允许并列写,编译器会自动归并) - 反例:想对
NullPointerException打告警,对IOException重试 —— 这种必须拆开 - 注意:多重捕获不会改变异常传播顺序,它只是语法糖,底层仍是按 try 块执行路径抛出的那个异常实例
catch 多重捕获和 try-with-resources 一起用的坑
二者叠加时,try-with-resources 自动关闭资源可能抛出新异常(AutoCloseException),它会压制原始异常 —— 而这个压制行为在多重捕获下容易被忽略。
- 如果
try块抛出IOException,且close()抛出SQLException,最终你 catch 到的是IOException,但它的getSuppressed()里藏着SQLException - 多重捕获写成
catch (IOException | SQLException e)并不能捕获被压制的异常,它只捕获主异常 - 真要处理压制异常,得显式调用
e.getSuppressed()遍历,别指望多重捕获自动覆盖
Java 6 或 Android(旧版本)不支持多重捕获怎么办
没有替代语法,只能退回到传统方式:用最宽泛的父类捕获,再用 instanceof 分流。但要注意判空和类型安全。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:
catch (Exception e) { if (e instanceof IOException) { ... } else if (e instanceof SQLException) { ... } } - 避免直接强转:
(IOException)e可能抛ClassCastException - Android minSdk compileOptions.sourceCompatibility JavaVersion.VERSION_1_8,运行时仍无效








