例外處理(Exception Manager)

  • 何謂例外?

例外,是當程式在執行的過程中,發生了非預期的狀況,也可以說是非預期的錯誤,例如網路程式在進行資料傳輸時,網路突然的斷線,或是要開啓一個檔案時,該檔案卻不存在,以上的這些情形皆稱為例外。

較以往傳統對例外的處理方式,主要是利用if語法來判斷該段程式的執行結果是否正確,並對錯誤的情況做出適當的處理。但是使用if語法的缺點為程式會變的相當的冗長,一但要處理的例外狀況變多時,對於各種例外狀況的管理與維護將會是一件相當另人頭痛的事。在Java的語法中對於例外處理提供了另外一種機制,以物件化的方式來表達和種不同的例外狀況,並以try catch的架構來簡化例外處理的判斷。

例外處理的基本語法:

try{

例外的處理語法與swtich case相當的類似,都是以區塊的方式來將不同的例依各別的方式進行處理。而各種不同可能會發生的例外狀況,則皆以物件的方式來表達,我們可以直接利用Java內定義好的例外物件來做判斷,也可以自行定義適合的例外物件。

在Java中所有的例外都是Throwable的子類別,而在Throwable類別後主要又可以分為兩大子類別,分別是Err類別與Exception類別。

  • Err類別:Err類別主要是針對程式運作時發生錯誤的狀況,例外記憶體不足、堆疊溢位等..,這類的錯誤通常很難預期何時會發生,發生往往都會造成系統嚴重的錯誤,相對的也相當不容易做處理。,
  • Exception類別:Exception主要是用來捕捉程式束預期可能會發生的例外狀況,使用者可以利用此類別自訂所需的例外類別。

底下為部份Java己為我們訂義的一些例外類別:

  • NullPointException當物件指向Null時所發生的例外事件。
  • RuntimException執行時期所會發生的例外事件。
  • ClassNotFoundException找不到類別時所會發生的例外事件。
  • ClassCastException類別無法進行轉型時所發生的例外事件。
  • IOException有關IO處理所會發生的例外事件
  • ArithmeticException進行算術運算處理時,所會發生的例外事件。
  • InterrupedException進行中斷處理時所會發生的例外事件。
  • FileNotFoundException找不到檔案時會發生的例外事件。
  • NumberFormatException字串轉換數字格式不符時所會發生的例外事件。

  • 為您的程式加入例外處理

在Java的世界中,例外處理的運作方式相當的簡單,當程式在運作時發生自身無法處理的狀況時,便會將這個狀況往更上一個層級丟去,這裡指的上一個層級可能父類中所覆寫的函式,或是丟往上一個呼叫函式。有人丟出例外就必須有人撿,所以一但你所使用的Java函式有發出例外的可能,Java就會強制規定你必須對該例外做出回應動作,你可以選擇利用try catch將該例外抓取下來,並進行處理,或是不對例外做處理,而直接把發生的例外丟往呼叫上一層函式。簡單的說try區塊是負責接收程式所丟出的例外物件,而catch則是比較所接收到的例外物件是否己有訂義處理的方式。所以說一組try區塊可以同時搭配多組的catch區塊,依照不同的例外狀況做個各的處理動作。

下列範例為算術運算例外事件範例,當我們在進行算術運算時,若發生除以0的情況,便會發生此例外事件。在程式中利用try catch語法,將進行算術運算的程式片段給包裝起來,一但在此段程式碼中發生算術例外處理時,系統便捉取到例外事件的發生,並找到ArithmeticException例外時的處理方式。

【範例程式】除零例外:

package com.lattebox.exception;

【執行結果】

2

圖 414 算術例外範例執行結果

另一種例外處理方式為將例外事件丟往上一層函式中去處理,此時上一個函式就必須對接收到的例外事件做出處理,或是在繼續的往上層丟。下例為一個NumberFormatException範例,在此範例中,例外發生時並不會在該函式中立即的被處理,而是會被丟往上一層的函式中去進行例外的處理。在函式宣告時必須利用關鍵字throws關建字宣告所可以可以拋出的例外名稱,可以同時宣告多組例外物件只需在每個名稱後面加上逗號(,),在函式中則可利用throw關鍵字拋出例外物件,所拋出的例外必須是函式上所宣告的例外或是其子類別。

【範例程式】除零例外-丟出例外:

package com.lattebox.exception;

【執行結果】

2

圖 415 自行丟出除零例外

  • 自行定義所需的例外

到目前為止我們所使用的例外類別都是Java為我們所訂義好的,雖然Java所提供的例外類別己相當的豐富,但還是有許多比較特別的例外狀態,是Java的例外類別中無法提供的,此時就必須量身訂做一個專屬的例外類別,以更符何程式的設計需求。

在先前我們有介紹過,所有的例外類別都是Throwable的子類別,因此我們只需要找一個Throwable底下的子類別來繼承,就可以建立一個獨立的例外例別。如下範例為一個自定例外類別,繼承至Exception類別,

【範例程式】自訂例外-定義例外類別

//RangeException.java 自定例外類別

在定義完一個獨立的例外類別後,接著我們要為該例外決定拋出的時機,也就是定義所處理的例外狀況為何,這完全是由程式設計員依程式的需求而定,只要認定有該例外狀況發生,便可以依據此例外類別建立新的例外物件,並利用throw關鍵字將例外物件丟出,當然在丟出例外所屬的函式上也必須利用throws關鍵字宣告可丟出RangeException類別,最後例外類別將會傳回到呼叫該函式的來源,並同時被try catch機制所捕捉,做出適當的回應或處理。在本範例中RangeException將被定位為處理輸入值範圍錯誤的狀況,例如一個成積輸入函式,應當輸入的數值範圍為0~100分,若輸入數直不在此範圍中,則將會拋出RangeException例外。以下為一個簡單的計算成積平均程式,在陣例中存放著不同人的考試成積,但其中有二個人的輸入值有誤,一個超過了100分,一個則為負數,兩者都並不在規定的0~100的範圍內,此時RangeException例外就會被發出,並顯示錯誤訊息於螢幕上。

【範例程式】自訂例外-拋出例外

package com.lattebox.exception;

【執行結果】

2

圖 416 計算平均成積範例執行結果