通过catch捕获底层异常并封装为高级异常,如将SQLException转换为ServiceException,保留异常链便于排查,实现各层解耦与统一处理。

在Java中,捕获并转换异常类型是一种常见的做法,目的是将底层异常(如SQLException、IOException)封装为更高级别或自定义的异常,从而提升代码的可维护性和调用方的使用体验。这种做法有助于隐藏实现细节,统一异常处理逻辑。
捕获异常并重新抛出
使用 try-catch 块可以捕获特定异常,并将其转换为另一种异常类型。通常会保留原始异常作为新异常的“原因”,以便保留完整的堆栈信息。
示例:假设有一个数据访问方法可能抛出 SQLException,但我们希望对外暴露一个更通用的 ServiceException。
public void saveUserData(User user) throws ServiceException {
try {
// 可能抛出 SQLException 的操作
userDao.save(user);
} catch (SQLException e) {
throw new ServiceException("保存用户失败", e); // 将 SQLException 包装为 ServiceException
}
}
这里的 ServiceException 是自定义异常类,继承自 Exception 或 RuntimeException。
立即学习“Java免费学习笔记(深入)”;
自定义异常类
为了支持异常转换,需要先定义自己的异常类型。
public class ServiceException extends Exception {
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
确保构造函数接收 message 和 cause 参数,这样就能链式追踪异常源头。
在多层架构中转换异常
常见于 DAO → Service → Controller 架构中:
- DAO 层捕获 SQLException,转换为 DataAccessException
- Service 层捕获数据访问异常,转换为业务相关的 ServiceException
- Controller 层统一处理 ServiceException 并返回友好提示
这样每一层只关心自己领域的异常类型,解耦清晰。
使用 try-with-resources 自动处理资源
当涉及 IO 或数据库连接时,try-with-resources 能自动管理资源关闭,但仍需处理可能的异常转换。
try (Connection conn = DriverManager.getConnection(url);
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.executeUpdate();
} catch (SQLException e) {
throw new ServiceException("执行SQL失败", e);
}
即使资源自动关闭,仍需捕获主操作中的异常并进行转换。
基本上就这些。关键是通过 catch 捕获原异常,构造新异常时传入原异常作为 cause,保持异常链完整,便于排查问题。这种方式既规范又实用。










