java 捕捉多個exception

在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子句捕獲的多個異常中的一個異常類型的父類或子類。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章