java捕获多重异常需用多个catch块按子类优先顺序排列,或用多异常捕获(|)配合instanceof判断类型;禁止父类在前、避免宽泛兜底,运行时异常应修复而非捕获。

Java 中捕获多重异常并做不同分支处理,核心在于明确“多重”是指多种类型异常同时可能出现,但每次实际只抛出一种;处理目标是让每种异常走各自逻辑路径。不能靠一个 catch 块“同时处理多个异常”,而要通过结构设计实现分而治之。
用多个 catch 块按子类优先顺序排列
这是最常用、语义最清晰的方式。JVM 按 catch 块从上到下的顺序匹配异常类型,一旦命中就执行对应块,后续不再检查。
- 子类异常必须写在父类前面,否则编译报错:
exception XXX has already been caught - 例如
FileNotFoundException是IOException的子类,必须先 catch 前者 - 常见层级:NumberFormatException ← IllegalArgumentException ← RuntimeException
示例:
try {
int a = Integer.parseInt(input);
FileReader fr = new FileReader(filename);
// ...
} catch (NumberFormatException e) {
log.warn("输入不是有效数字", e);
return handleInvalidInput();
} catch (FileNotFoundException e) {
log.error("配置文件缺失,启用默认配置", e);
loadDefaults();
} catch (IOException e) {
log.error("读取文件失败,可能权限或磁盘问题", e);
throw new ServiceException("文件访问异常", e);
}
用多异常捕获(|)+ instanceof 区分处理
Java 7+ 支持单个 catch 块捕获多个互不继承的异常,如 catch (IOException | SQLException e)。但变量 e 的静态类型是它们的最小公共父类(如 Exception),无法直接调用子类特有方法。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 若需差异化处理,可在该 catch 块内用
instanceof判断具体类型 - 注意:所有异常类型之间不能有继承关系,否则编译失败
- 适合业务含义相近、恢复策略相似的异常组合(如多种数据访问异常)
示例:
try {
saveToDatabase();
sendToQueue();
} catch (SQLException | JMSException e) {
if (e instanceof SQLException) {
retryWithNewConnection();
} else if (e instanceof JMSException) {
checkQueueBrokerStatus();
}
log.error("持久化或投递失败", e);
}
避免兜底过宽,保留异常语义
不要把 Exception 或 Throwable 放在第一个 catch 块,否则它会拦截所有后续异常,导致编译失败或逻辑失效。
- 把
catch (Exception e)放在最后,仅作为保底,且应记录完整堆栈、触发告警 - 绝对不要捕获
Throwable(含OutOfMemoryError等),这会干扰 JVM 正常终止 - 运行时异常(如
NullPointerException)通常反映代码缺陷,应优先修复而非捕获
配合 try-with-resources 处理资源关闭异常
当使用 try-with-resources 时,业务异常和资源关闭异常可能同时发生。JVM 会将关闭异常作为“被抑制异常”附加到主异常上,不会进入任何 catch 块。
- 主异常(如
IOException)正常被捕获 - 被抑制的异常(如
SQLException)需通过e.getSuppressed()显式获取 - 若需统一响应,建议在 catch 块中检查并合并日志,而不是试图在同一个 catch 中捕获两者
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










