【Java7新特性】同时捕获多个异常类型

在Java SE 7中,你可以使用单个catch语句块处理一种或多种类型的异常,并以改进的异常类型检查方式来重新抛出异常。

我们先来看一段代码:

catch (IOException ex) {
     logger.log(ex);
     throw ex;
catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

在Java SE 7发布之前,由于变量ex存在不同的类型,因此想要创建一个公共方法来清除重复的代码是非常困难的。不过从Java SE 7版本开始,你可以编写如下代码来去除重复的代码:

//多个异常类型之间用"|"隔开
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

注意:如果一个catch语句块处理的异常类型超过1个,那就隐式地表示被catch的参数变量(例如上面的ex)是一个final的变量,你不能在catch语句块内对其重新赋值。

使用单个catch语句块处理多种异常类型比使用多个catch语句块,每个语句块只处理一种类型的异常所编译生成的字节码更小,因此也更好。一个处理多个异常类型的catch语句块在被Java编译器编译时并不会生成重复的字节码,字节码中也没有重复的异常处理程序。

与以前版本相比,Java SE 7 的编译器能够对再次抛出的异常(rethrown exception)做出更精确的分析。这使得你可以在一个方法声明的throws从句中指定更具体的异常类型。我们先来看下面的一个例子:

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName) throws Exception {
    try {
        if (exceptionName.equals("First")) {
            throw new FirstException();
        } else {
            throw new SecondException();
        }
    } catch (Exception e) {
        throw e;
    }
 }

这个例子中的try语句块可能会抛出FirstException或者SecondException类型的异常。设想一下,你想在rethrowException方法声明的throws从句中指定这些异常类型。在Java SE 7之前的版本,你无法做到。因为在catch子句中的异常参数ejava.lang.Exception类型的,catch子句对外抛出异常参数e,你只能在rethrowException方法声明的throws从句中指定抛出的异常类型为java.lang.Exception (或其父类java.lang.Throwable)。

不过,在Java SE 7中,你可以在rethrowException方法声明的throws从句中指定抛出的异常类型为FirstExceptionSecondException。Java SE 7的编译器能够判定这个被throw语句抛出的异常参数e肯定是来自于try子句,而try子句只会抛出FirstExceptionSecondException类型的异常。尽管catch子句的异常参数ejava.lang.Exception类型,但是编译器可以判断出它是FirstExceptionSecondException类型的一个实例:

public void rethrowException(String exceptionName) throws FirstException, SecondException {
    try {
        // ...
    } catch (Exception e) {
        throw e;
    }
}

不过,如果catch捕获的异常变量在catch子句中被重新赋值,那么异常类型检查的分析将不会启用,因此在这种情况下,你不得不在方法声明的throws从句中指定异常类型为java.lang.Exception

更具体地说,从Java SE 7开始,当你在单个catch子句中声明一种或多种类型的异常,并且重新抛出这些被捕获的异常时,需符合下列条件,编译器才会对再次抛出的异常进行类型验证:

  • try子句会抛出该异常。

  • 在此之前,没有其他的catch子句捕获该异常。

  • 该异常类型是catch子句捕获的多个异常中的一个异常类型的父类或子类。


赞(52) 打赏
未经允许不得转载:优客志 » JAVA开发
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏