From Gossip@caterpillar

Java Gossip: 簡介例外處理

在還沒有學習例外處理之前,如果您要撰寫一個除法程式,並由使用者輸入除數與被除數,由於被除數除以0沒有意義,所以之前可能 必須像以下這樣避免錯誤:
if(b != 0)
    System.out.println(a / b);
else
    System.out.println("除數不能為0");

這樣的方式過去在一些程式語言中會很常被利用,利用判斷式來避免錯誤的發生,然而這樣的方式會讓錯誤處理與程式的處理邏輯混在一起,使得程式難以閱讀,而 由於使用了一些判斷式,即使有一些很少發生的錯誤,也都必須一視同仁的進行判斷檢查,這會使得程式的執行效能受到一定程度的影響。

Java的例外處理機制可以協助我們捕捉程式執行時期的錯誤,它用來處理一些系統可以恢復的錯誤,例外(Exception)是Java中定義 的一種物件資料型態,在特定錯誤發生時會丟出例外物件,我們可以捕捉這些例外並加以處理,避免程式可能的錯誤發生。

Java的例外處理藉由"try""catch""finally"三個關鍵字組合的語言來達 到,其語法基本結構如下:
try {
    // 陳述句
}
catch (例外型態 名稱) {
    // 例外處理
}
finally {
    // 一定會處理的區塊
}

一個"try"所包括的區塊,必須有對應的"catch"區塊,它可以有多個"catch"區域,而"finally"可有可無,如果沒有定義 "catch"區塊,則一定要有"finally"區塊。

先來看個實例,瞭解如何使用try...catch來處理使用者輸入的錯誤:
  • UseException.java
import java.io.*; 

public class UseException {
public static void main(String[] args) {
try {
int input;
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("請輸入整數: ");
input = Integer.parseInt(buf.readLine());
System.out.println("input x 10 = " + (input*10));
}
catch(IOException e) {
System.out.println("I/O錯誤");
}
catch(NumberFormatException e) {
System.out.println("輸入格式有誤");
}
}
}

例外處理是程式在執行但發生錯誤並無法處理時,會丟出一個例外物件,在這個程式中,您特意 使用 BufferedReader 取得輸入,當使用 BufferedReader類別時,若發生I/O錯誤會丟出IOException 例外,這個例外您必須處理。

您試著從使用者輸入取得一個整數值,由BufferedReader物件所讀取到的輸入是個字串,您使用Integer類別的 parseInt()方法試著剖析該字串為整數,如果無法剖析,則會發生錯誤並丟出一個NumberFormatException例外物 件,當這個例外丟出後,程式會離開目前執行的位置,而如果設定的"catch"有捕捉這個例外,則會執行對應區塊中的陳述句,注意當例外一但丟出,就不會 再回到例外的丟出點了。

來看看這個程式的執行範例:

$ java UseException
請輸入整數: 10
input x 10 = 100
$ java UseException
請輸入整數: XX
輸入格式有誤

 
如果程式中設定有"finally"區塊,則無論例外是否有發生,則一定會執行"finally"區塊中所定義的陳述句, "finally"區塊使用時機 的例子之一,就是當您開啟了某個檔案時,在讀/寫的過程中發生錯誤,在使用"catch"區塊處理相對應的例外之後,最後在"finally"區塊中定義 一些關閉檔案的動作,讓關閉檔案的動作一定會被執行。

使用例外處理的好處是您可以將程式邏輯與錯誤處理分開,使得程式易於撰寫、閱讀與維護,由於例外處理是在程式執行時發生錯誤,而沒有辦法處理之時才產生例 外物件,所以與使用判斷式來避免例外的方式比起來,例外處理會有比較好的執行效能。