抛出子异常,捕获为超级异常并重新抛出它但声明抛出子异常

Throw Sub-Exception, catch as Super Exception and re-throw it but declare throws Sub-Exception

Java 文档在处理类型转换时清楚地解释了对象一致性,return 类型的覆盖方法以及抛出和捕获异常。但现在我对异常有点困惑,这段代码背后隐藏的概念是什么..

void getNames() throws SQLClientInfoException { /*throws Subclass object to caller*/
    try{
        // throwing Subclass object to catch block but up-casting to Exception
        throw new SQLClientInfoException(); 
    } catch (Exception e) {
        throw e; /* re-throwing throwing as Exception 
    }
}

因为 SQLClientInfoException 是 "java.lang.Exception" 的 子类,所以在 SQLClientInfoException 被抛出时被 catch 块捕获

"e" catch 块中的变量引用 SQLClientInfoException。

它是 Java SE 7 中引入的编程语言的一个特性 - 在异常中使用更精确的重新抛出。

Java SE 7 编译器比 Java 的早期版本对重新抛出的异常执行更精确的分析。这使得可以在方法声明的 throws 子句中指定更具体的异常类型。

之前 Java 7:

void aMethod() throws CustomDbException {
    try {
        // code that throws SQLException
    }
    catch(SQLException ex) {
        throw new CustomDbException();
    }
}
  • 在catch块中重新抛出异常不需要指明 try 块中可能出现的实际异常。
  • 抛出的异常类型不改就改不了 方法签名。

在 Java 7 或更高:

void aMethod() throws IOException {
    try {
        Files.copy(srcePath, trgtPath); // throws IOException
    }
    catch(Exception ex) {
        throw ex;
    }
}

以上代码在Java7.

中是合法的
  • 如果在try子句中抛出某种类型的异常,并且在catch子句中没有分配异常变量,编译器会复制try块中可以抛出的已检查异常类型。 (如果不重新分配异常变量,就好像从 try 块中抛出所有可能的异常)。
  • 编译器知道唯一可能的异常类型是 IOException(因为那是 Files.copy() 可以抛出的)。

另请参阅 Oracle 网站上的这篇文章:Rethrowing Exceptions with More Inclusive Type Checking