java 捕捉多个exception

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

我们先来看一段代码:

 
 
  1. catch (IOException ex) {
  2.      logger.log(ex);
  3.      throw ex;
  4. catch (SQLException ex) {
  5.      logger.log(ex);
  6.      throw ex;
  7. }

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

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

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

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

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

 
 
  1. static class FirstException extends Exception { }
  2. static class SecondException extends Exception { }
  3. public void rethrowException(String exceptionName) throws Exception {
  4.     try {
  5.         if (exceptionName.equals("First")) {
  6.             throw new FirstException();
  7.         } else {
  8.             throw new SecondException();
  9.         }
  10.     } catch (Exception e) {
  11.         throw e;
  12.     }
  13. }

这个例子中的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类型的一个实例:

 
 
  1. public void rethrowException(String exceptionName) throws FirstException, SecondException {
  2.     try {
  3.         // ...
  4.     }
  5.     catch (Exception e) {
  6.         throw e;
  7.     }
  8. }

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

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

  • try子句会抛出该异常。
  • 在此之前,没有其他的catch子句捕获该异常。
  • 该异常类型是catch子句捕获的多个异常中的一个异常类型的父类或子类。

猜你喜欢

转载自blog.csdn.net/liudsl/article/details/79834267