异常包装
什么是异常包装?
异常包装是指当我们捕获一个异常,将其包装在另一个异常中并抛出该异常时进行包装。这是一个例子:
try{ dao.readPerson(); } catch (SQLException sqlException) { throw new MyException("error text", sqlException); }
方法dao.readPerson()可以引发SQLException。如果是这样,则将捕获SQLException并将其包装在MyException中。注意如何将SQLException(sqlException变量)作为最后一个参数传递给MyException的构造函数。
自JDK 1.4起,异常包装是Java中的标准功能。 Java的大多数内置内置异常(如果不是全部)都具有可以采用" cause"参数的构造函数。它们还具有getCause()方法,该方法将返回包装的异常。
为什么要使用异常包装?
使用异常包装的主要原因是为了防止代码进一步向上调用堆栈,而不必知道系统中每个可能的异常。这有两个主要原因。
第一个原因是,声明的异常聚集在调用堆栈的顶部。如果我们不包装异常,而是通过声明抛出它们的方法来传递它们,则最终可能会使用声明许多不同异常的顶级方法。在每个方法中声明所有这些异常以备份调用堆栈变得很乏味。
第二个原因是,我们可能不希望顶级组件了解有关底层组件的任何信息,也不希望它们抛出的异常。例如,DAO接口和实现的目的是将数据访问的详细信息从应用程序的其余部分中抽象出来。现在,如果DAO方法抛出SQLException,则使用DAO的代码将必须捕获它们。如果更改为从Web服务而不是从数据库读取数据的实现,该怎么办?然后,DAO方法将必须同时抛出RemoteException和SQLException。而且,如果我们有一个DAO可以从文件中读取数据,则也需要抛出IOException。那是三个不同的例外,每个例外都绑定到自己的DAO实现。
为了避免这种情况,DAO接口方法可以抛出DaoException。在DAO接口的每个实现(数据库,文件,Web服务)中,我们将捕获特定的异常(SQLException,IOException,RemoteException),将其包装在DaoException中,然后抛出DaoException。然后,使用DAO接口的代码将只需要处理DaoException。它不需要知道各种实现中使用了哪种数据访问技术。