圖片來源:《Java Idioms: Exception Handling》。
昨天談到如何處理例外,今天接著說明如何宣告例外。在這裡所提到的「宣告例外」,是指將Java的check exception宣告在method的signature上面。例如:
public readFile() throws IOException
如何宣告例外
在說明如何宣告例外之前,先談一下何時需要宣告例外。基本上有兩個情況導致method丟出例外:
- 該method自己的實作發生例外但不知該如何處理,因此將此例外直接往外丟希望讓呼叫它的人有機會可以處理這個例外狀況。
- 該method自己的實作發生例外且已經想辦法處理了這個例外。但不幸地這個例外處理程式失敗了,因此將此例外往外丟希望讓呼叫它的人有機會可以處理這個例外狀況。
關於例外類別的使用與如何宣告例外在《Java Idioms: Exception Handling》這篇論文中有詳細的說明,文章中介紹了11個Java例外處理(主要是如何使用例外類別)模式(pattern),寫得蠻好的,有興趣的鄉民們值得花點時間一讀。Teddy今天想要介紹一下其中的Homogeneous Exception(同質例外)的概念。
***
Java的check exception有一個很討厭的地方(事實上不只一個),就是如果一個method遇到了好幾個不同類別的例外,而這個method又無力去處理,想要把這些例外往外丟。如果同時將這個例外都宣告在signature中,就會發生很恐怖的事情。請直接看範例:
public readFile() throws IOException, ClassNotFoundException, SQLException { // 這個method的實作會遇到三個例外:IOException、ClassNotFoundException、SQLException }
這種做法有兩個問題:
- 不易使用:readFile()變得很難使用,因為呼叫它的人要面對好幾個不同的例外類別。
- 暴露實作細節:萬一有一天readFile()的實作改了,不再丟出SQLException但改丟出一個新的DestroyFailedException。因為readFile()的signature改變了,原本呼叫readFile()的人都會被影響。
public readFile() throws FailureException { try{ // 這個method的實作會遇到三個例外:IOException、ClassNotFoundException、SQLException } catch(IOException e) { throw new FailureException(e); } catch(ClassNotFoundException e) { throw new FailureException(e); } catch(SQLException e) { throw new FailureException(e); } }
***
改用Homogeneous Exception的做法,當readFile()執行失敗時,呼叫它的人會收到FailureException的通知。如果要知道發生失敗的原因(root cause)是因為IOException、ClassNotFoundException或是SQLException所引起的,也可以從Exception物件的getCause()這個method所得之 ,同時解決了上述不易使用與暴露實作細節的問題。
***
友藏內心獨白:如何使用例外物件還有很多「眉角」啊。
沒有留言:
張貼留言