天天看點

Java程式設計基礎之異常處理

早期的程式設計語言(比如C語言)沒有異常處理,通常是遇到錯誤傳回一個特殊的值或設定一個标志,并以此判斷是不是有錯誤産生。随着系統規模的不斷擴大,這種錯誤處理已經成為建立大型可維護程式的障礙了。于是在一些語 言中出現了異常處理機制,比如在Basic中的異常處理語句“on error goto”,而Java則在C++基礎上建立了新的異常處理機制。

Java通過面向對象的方法進行異常處理,把各種不同的異常進行分類,并提供了良好的接口。這種機制為複雜程式提供了強有力的控制方式。同時這些異常代碼與“正常”代碼分離,增強了程式的可讀性,編寫程式時也顯得更靈活。

異常處理還有一個好處是在你不能确定和處理異常時,你可以不處理,而把問題送出上去。另一方面,異常處理機制使得錯誤處理代碼更有條理,更便于維護。下面,我們看看在Java中如何處理異常。

Java中的異常類

在Java中,每個異常都是一個對象,它是Throwable類或其它子類的執行個體。當一個方法出現異常後便抛出一個異常對象,該對象中包含有異常資訊,調用這個對象的方法可以捕獲到這個異常并進行處理。

Throwable類有兩個标準子類:java.lang.Error和java.lang.Exception即錯誤和異常。錯誤Error類一般是指虛拟機相關的問題,如系統崩潰、虛拟機出錯誤、動态連結失敗等,這一類錯誤無法恢複或不可能捕獲,将導緻應用程式中斷。異常Exception類則是指一些可以被捕獲且可能恢複的異常情況,如數組下标越界ArrayIndexOutOfBoundsExcepton、數字被零除産生異常ArithmeticException、輸入/輸出異常IOException等。

提示:Java編譯器要求Java程式必須捕獲或聲明所有非運作時的異常,如:FileNotFoundException、IOException等。因為,對于這類異常來說,如果程式不進行處理,可能會帶來意想不到的結果。但運作時出現異常可以不做處理,因為這類異常很普遍,全部處理可能對程式的可讀性和運作效率産生影響。

Java異常處理形式

Java的異常處理是通過5個關鍵詞來實作的:try、catch、throw、throws和finally。一般情況下是用try來執行一段程式,如果出現異常,系統會抛出(throws)一個異常,這時候你可以通過它的類型來捕捉(catch)它,或最後(finally)由預設處理器來處理。

下面是Java異常處理程式的基本形式:

try 

//執行時程式塊

catch ExceptionType1e

//對ExceptionType1的處理

catch ExceptionType2e

//對ExceptionType2的處理

throw e

//再抛出這個“異常”

finally 

程式塊和catch語句

遇到一個try語句,“異常”的架構就放到堆棧上面,直到所有的try塊内的語句都完成。如果下一級的try語句沒有對某種“異常”進行處理, 堆棧就會展開,直到遇到有處理這種“異常” 的try語句。在try程式後面,應包含一個catch子句來指定你想要捕捉的“異常”的類型。

提示:捕獲異常的第一步就是用try…標明你要捕獲異常的範圍,在執行時,括号内的代碼會産生異常對象并被抛出。然後你就可以用catch塊來處理異常了。

throw語句和throws語句

throw語句用來明确地抛出一個“異常”。首先,你必須得到一個Throwable類或其它子類産生的執行個體句柄, 通過參數傳到catch子句,或者用new語句來建立一個執行個體。

下面是throw語句的通常形式:

throw ThrowableInstance

提示:執行throw語句後,運作流程将立即停止,throw的下一條語句也将暫停執行。這裡new運算符用于建立一個Throwable類的執行個體,在後文的面向對象程式設計一文中将詳細講解。

throws語句用來标明一個成員函數可能抛出的各種“異常”。對大多數Exception子類來說,Java編譯器會強迫你聲明在一個成員函數中抛出的“異常”的類型。如果“異常”的類型是Error或RuntimeException,或它們的子類,這個規則不起作用。如果你想明确地抛出一個RuntimeException,你必須用throws語句來聲明它的類型。

提示:當然,你可能對上面的說明不是很明白,不過不要緊,編譯運作下面的Java程式(已經為你做了詳細的注釋)你會了解很多!

現在我們用下面的例程來說明問題:

class ThrowsDemo  //類名,相應的java源檔案應該儲存成:ThrowsDemo.java

static void procedure  throws Illegal

AccessException //throws語句

//抛出IllegalAccessException類型的異常

System.out.println″inside procedure″ //輸出文本資訊,以說明是在執行proced

ure方法時抛出了異常

throw new IllegalAccessException″de

mo″ //新生成一個Throwable類執行個體,然後抛出異常

public static void mainString args //main方法開始,程式從此處執行

 try  //try語句塊開始

procedure  //調用procedure方法,該方法将Throw(抛出)異常資訊

catch IllegalAccessException e

 //處理IllegalAccessException類型的異常,catch語句塊

System.out.println″caught ″ + e 

程式設計并執行程式,其過程如下:

E/javacode/exception>java ThrowsDe

mo

inside procedure

caught java.lang.IllegalAccessExceptio

n demo

提示:如上面的代碼所示,我們用了一個完整的程式來說明在Java程式中如何使用try…catch…throw等語句。Try…裡産生的異常被捕獲了下來,然後在catch塊裡進行處理(這裡隻是輸出異常資訊)。throws IllegalAccessException标明程式将抛出一個IllegalAccessException類型的異常。IllegalAccessException e生成一個異常對象,然後用System.out.println輸出異常資訊。

finally語句

有時為了確定一段代碼不管發生什麼異常都要被執行,可以使用關鍵詞finally來标出這樣一段代碼。一個成員函數傳回到調用它的成員函數,或者通過一個沒捕捉到的異常,或者通過一個明确的return語句,finally子句總是恰好在成員函數傳回前執行。

下面我們以一個比較完整的異常處理程式來說明上面所述的各種異常處理語句的使用問題:

class ExceptionDemo  //異常使用示例,儲存為ExceptionDemo.java

static void procA 

try

System.out.println″inside procA″

throw new RuntimeException″demo″

//抛出異常

finally 

System.out.println″procA's finally″ //注意:不管發生什麼等會執行!!

static void procB 

 try 

System.out.println″inside procB″

return //傳回,實際上是在finally語句執行完後才傳回

finally 

System.out.println″procB's finally″

public static void mainString args

 try

procA

catchException e

System.out.println″catch″+e

procB 

提示:在上面的完整程式中,finally後的大括号内的代碼是任何情況下都會執行的。另外,在procB 中,return語句并沒有立即傳回,這一點應該特别注意。你可以親自動手,執行上面的程式試試(編譯和執行類似于上例)?

到目前為止,關于Java的流程控制已經完全講完了。要真正了解并掌握它們隻有經過大量的練習。而好的方法就是修改上面的每一個程式,讓它們實作你想要的功能,并在此基本上了解Java的流程控制。而要寫好Java程式,熟悉使用Java的流程控制和異常處理是非常關鍵的。是以在這兩期中,我們用大量的例程來說明Java語言是如何使用流程控制語句的,并且對流程控制中經常使用的異常處理語句做了簡單的介紹。