在 Java 中常常會遇到該捕捉例外卻沒有捕捉, 編譯時發出錯誤的狀況, 到底哪些例外一定要捕捉、哪些不必呢?其實只要知道 Java 中例外類別的階層關係與其所代表的意涵, 就可以判斷了。
只有受檢查例外才需要捕捉處理
在 Java 中, 透過例外機制處理的狀況都會包裝成 Throwable 子類別的物件, 這又可以分為兩大類:
- Error 類別家族:代表發生了通常無法復原的嚴重錯誤, 例如 OutOfMemoryError 代表記憶體不足, 程式無法解決這樣的問題。
- Exception 類別家族:代表執行期間的各種意外狀況, 例如無法找到指定檔案的 FileNotFoundException。其中 RuntimeException 類別子家族代表的是程式面沒有考慮周詳造成的意外狀況, 像是除以 0 的 ArithmeticException, 屬於程式員可以完全掌控, 修正程式即可避免的意外。
上述幾大類的例外類別繼承結構如下:
java.lang.Throwable
|
+---java.lang.Error
| |
| +....
|
+---java.lang.Exception
|
+....
|
+java.lang.RuntimeException
|
+....
其中, Error 和 RuntimeException 兩大類合稱為不受檢查 (unchecked) 的例外, 並不強制一定要捕捉處理:
Error 是無法復原的狀況, 像是記憶體不足, 捕捉了也無濟於事, 程式無法補救, 即使通知使用者, 使用者也不能做什麼處理。
RuntimeException 則是程式員自己的疏失, 像是除以 0 的狀況就是程式沒有確實檢查才會發生, 引發例外中斷程式執行可以迫使開發者回頭修正程式, 加上必要的檢查避免引發例外。
反之, 其他類的例外就稱為受檢查 (checked) 的例外, 一定要在宣告方法時以 throws 指明可能發生的例外, 叫用此方法時也必須要捕捉並處理例外, 或是以 throws 交由更外層的程式處理。以剛剛舉例的 FileNotFoundException 來說, 程式應該要補抓例外, 並通知使用者, 讓使用者把檔案補上或是改指定其他路徑讀取檔案等等。
Java 文件中的標示方法
在 Java 的 API 文件中, 可以明確區分個別方法可能會拋出的不受檢查例外與受檢查的例外, 以下以 Reader 類別的 skip 方法為例:
圖中上方紅框內寫在方法原型中的 IOException 就是受檢查的例外, 例如正在讀取中的檔案所在的隨身碟被拔掉, 就會引發 IOException。標示在下方紅框內解說結尾處的就是所有可能發生的例外, 這裡包含了程式員沒注意傳入負值時發生的 IllegalArgumentException 例外。
只要查看文件, 就可以分清楚一定要處理哪些例外, 而哪些例外不用特別處理, 或是發生時要請使用者通知你修正程式。
結語
弄清楚受檢查的例外與不受檢查的例外, 不但可以幫助你決定在程式中要處理哪些例外, 如果你需要自訂例外類別, 也可以分清楚應該要將類別歸屬在哪一個家族下, 否則別人使用你撰寫的類別時, 也會發生該捕捉的例外沒捕捉, 反而捕捉了應該是你撰寫程式時疏忽的狀況, 導致程式中潛藏的問題反而沒有好好處理, 那就麻煩了。
Top comments (0)