Java - 例外處理 -- 何時該用try/catch?何時該用throws?

發現這個問題容易被忽略,卻很重要,也是有些人包括我都有的疑問。

Java例外處理須注意細節部分滿多,這篇只針對錯誤「該拋還是該處理」做個重點說明:


首先,先了解相關名詞定義:


Java的錯誤以物件呈現。java.lang.Throwable類別下,有2個子類別:
1. 代表嚴重系統錯誤的「java.lang.Error」。
2. 代表程式設計本身錯誤的「java.lang.Exception」。

A. Exception或其子物件(但不是RuntimeException或其子物件):稱為「受檢例外」(Checked Exception
受檢例外定義:當設計API的人實作某方法時,某些條件成立下會引發錯誤 => 認定呼叫方法的客戶端有能力處理錯誤,要求編譯器提醒客戶端需明確處理錯誤,否則編譯失敗的例外。e.g. IOException

B. RuntimeException或其子物件:稱為「非受檢例外」(Unchecked Exception
非受檢例外定義:當設計API的人實作某方法時,當某些條件成立下會引發錯誤 =>認為API客戶端應在呼叫方法前做好檢查才呼叫方法,避免發生錯誤。而編譯器不會強制提醒要處理錯誤。e.g. ArrayIndexOutOfBoundsException


開始說明錯誤「該拋還是該處理」:


  • 設計時無充足資訊知道該如何處理,如:不知道會用在「主控台環境」或「Web環境」,那就可選擇寫throws去拋出例外,讓呼叫方法的客戶端處理。

  • 如果過程中會拋出「受檢例外」,但目前環境資訊不足以處理例外,沒法用try catch處理時,可由「呼叫方法的客戶端」依當時呼叫的環境資訊去做處理。用throws去宣告該方法,以拋出的「例外類型」或「父型別」。

  • 拋受檢例外,代表我們認為呼叫方法的客戶端「有能力」且「應處理」例外,應用throws,至於要throws哪個類型,客戶端可查API得知,不需查看程式。

  • 在例外發生時,可用try catch先處理「當時環境可做的例外處理」。而「當時環境無法決定如何處理的部分」,可用throw拋到呼叫方法的客戶端處理。throw可拋「受檢例外」或「非受檢例外」。
    e.g. 
    try {
    //TODO
    } catch (FileNotFoundException ex) {
    ex.printStackTrace();
    throw ex;
    }

    return ok”;
  • 如認為客戶端呼叫方法的時機不當,而引發錯誤 => 希望客戶端「做好前置條件檢查再呼叫」時,可拋出非受檢例外。
  • 非受檢例外的情形,編譯器不會要求需使用try catchthrows,例外應就任其向外傳播 => 不該用try catch,而是應改善程式邏輯(也就是請客戶端debug此錯誤後再呼叫)以避免錯誤發生。

留言

熱門文章