全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-08 6 分钟 ✍️ juanwangdev

异常链与多重捕获

异常链保留原始异常信息,多重捕获简化多异常处理。

异常链

什么是异常链

异常链是在包装异常时保留原始异常(cause),便于追踪错误根源。

Java
try {
    // 原始异常
    int result = 10 / 0;  // ArithmeticException
} catch (ArithmeticException e) {
    // 包装异常,保留原始异常作为cause
    throw new BusinessException("计算失败", e);
}

构造异常链

使用带Throwable参数的构造方法。

Java
// 方式1:构造时传入cause
try {
    readFile();
} catch (IOException e) {
    throw new BusinessException("业务处理失败", e);  // e作为cause
}

// 方式2:使用initCause
try {
    connect();
} catch (SQLException e) {
    BusinessException ex = new BusinessException("连接失败");
    ex.initCause(e);  // 设置cause
    throw ex;
}

获取cause信息

Java
try {
    // ...
} catch (BusinessException e) {
    // 获取包装异常信息
    String message = e.getMessage();  // "业务处理失败"
    
    // 获取原始异常
    Throwable cause = e.getCause();
    if (cause != null) {
        String causeMsg = cause.getMessage();  // 原始异常消息
        cause.printStackTrace();              // 原始异常堆栈
    }
}

异常链堆栈输出

Java
public void method() {
    try {
        int x = 10 / 0;
    } catch (ArithmeticException e) {
        throw new BusinessException("计算错误", e);
    }
}

// 输出堆栈
BusinessException: 计算错误
    at Test.method(Test.java:5)
Caused by: ArithmeticException: / by zero
    at Test.method(Test.java:3)

"Caused by"显示原始异常信息,便于定位根本原因。

异常链使用场景

场景说明
业务层包装将技术异常转换为业务异常
API封装对外暴露统一异常类型
分层架构每层添加上下文信息
错误追踪保留完整错误链
Java
// 分层异常链示例
public void serviceMethod() throws ServiceException {
    try {
        daoMethod();
    } catch (DaoException e) {
        throw new ServiceException("服务层处理失败", e);
    }
}

public void daoMethod() throws DaoException {
    try {
        jdbcOperation();
    } catch (SQLException e) {
        throw new DaoException("数据访问失败", e);
    }
}

多重捕获

Java 7+多重捕获语法

一个catch块捕获多种异常类型,使用|分隔。

Java
// 传统方式:多个catch块
try {
    // ...
} catch (IOException e) {
    handleException(e);
} catch (SQLException e) {
    handleException(e);
}

// 多重捕获:一个catch块(Java 7+)
try {
    // ...
} catch (IOException | SQLException e) {
    handleException(e);  // 同一种处理方式
}

多重捕获优势

Java
// 简化重复代码
try {
    connect();
    query();
} catch (IOException | SQLException | ClassNotFoundException e) {
    logger.error("操作失败", e);
    throw new BusinessException("系统异常", e);
}

多重捕获规则

  • 异常类型不能有继承关系(不能同时捕获Exception和IOException)
  • catch块内异常变量是final的(不能重新赋值)
  • 多种异常共享同一种处理逻辑
Java
// 错误:类型有继承关系
try {
    // ...
} catch (IOException | Exception e) {  // 编译错误
    // IOException是Exception子类
}

// 正确:类型无继承关系
try {
    // ...
} catch (IOException | SQLException e) {  // 正确
    // IOException和SQLException无继承关系
}

异常链与多重捕获结合

实际应用示例

Java
public void processFile(String path) throws BusinessException {
    try {
        FileReader reader = new FileReader(path);
        // 处理文件
    } catch (FileNotFoundException | IOException e) {
        // 多重捕获,统一包装
        throw new BusinessException("文件处理失败", e);
    }
}

分层架构应用

Java
public class UserService {
    
    public User getUser(Long id) throws ServiceException {
        try {
            return userDao.findById(id);
        } catch (SQLException | IOException e) {
            // 多重捕获技术异常
            throw new ServiceException("获取用户失败", e);
        }
    }
    
    public void updateUser(User user) throws ServiceException {
        try {
            userDao.update(user);
        } catch (SQLException | IOException e) {
            throw new ServiceException("更新用户失败", e);
        }
    }
}

获取异常链信息

打印完整异常链

Java
try {
    // ...
} catch (Exception e) {
    e.printStackTrace();  // 自动打印Caused by链
}

// 输出:
ServiceException: 服务层错误
    at Service.method()
Caused by: DaoException: DAO层错误
    at Dao.method()
Caused by: SQLException: 数据库错误
    at Jdbc.operation()

手动遍历异常链

Java
public void printExceptionChain(Throwable e) {
    while (e != null) {
        System.out.println(e.getClass().getName() + ": " + e.getMessage());
        e = e.getCause();  // 获取下一层异常
    }
}

// 使用
try {
    // ...
} catch (Exception e) {
    printExceptionChain(e);
    // ServiceException: 服务层错误
    // DaoException: DAO层错误
    // SQLException: 数据库错误
}

要点总结

  • 异常链通过cause保留原始异常信息
  • 构造异常时传入cause:new Exception(msg, cause)
  • getCause()获取原始异常
  • printStackTrace()自动显示Caused by链
  • 异常链用于分层架构、业务包装
  • 多重捕获用|分隔多种异常类型(Java 7+)
  • 多重捕获类型不能有继承关系
  • catch变量是final的,不能重新赋值
  • 多重捕获简化重复处理代码
  • 异常链和多重捕获可结合使用

📝 发现内容有误?点击此处直接编辑

← 上一篇 异常的概念与分类
下一篇 → 自定义异常
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库