用異常來處理錯誤—-第三節 捕獲和處理異常

來源:互聯網
上載者:User

    這節說明怎樣使用異常處理器的三個組成部分-try,catch和finally塊來編寫異常處理器。最後舉一個例子,並且分析在不同的情況下發生了什麼。
    下面的例子定義和實現了一個叫做ListOfNumbers的類。在類的構造器中,ListOfNumbers建立了一個Vector,它包含了從0到9 的十個連續的整數。ListOfNumbers類也定義了一個叫writeList的方法,這個方法把這個數字列表寫入一個叫做OutFile.txt的文字檔中。這個例子使用了在java.io中定義的輸出類。
// 注意: 這樣的設計,這個類不會被編譯
import java.io.*;
import java.util.Vector;

public class ListOfNumbers {
    private Vector victor;
    private static final int SIZE = 10;
    public ListOfNumbers () {
        victor = new Vector(SIZE);
        for (int i = 0; i < SIZE; i++) {
            victor.addElement(new Integer(i));
        }
    }

    public void writeList() {
        PrintWriter out = new PrintWriter(
                            new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " +
                            victor.elementAt(i));
        }
        out.close();
    }
}
  這個例子中的第一行黑體字部分代碼調用了一個構造器,這個構造器初始化一個檔案輸出資料流。如果這個檔案不能被開啟,這個構造器會拋出一個 IOException異常。第二行黑體字部分代碼調用一個Vector類的elementAt方法,如果它的參數值太小(小於零)或太大(大於 Vector中當前所包含的元素數),那麼它會拋出一個ArrayIndexOutOfBoundsException異常。
如果試圖編譯ListOfNumbers類,編譯會列印一個有關被FileWrite構造器所拋出的異常的錯誤訊息。這是因為構造所拋出的 IOException異常是一個編譯檢查性異常,被elementAt方法拋出的ArrayIndexOutOfBoundsException異常是一個運行時異常,而Java程式設計語言只要求程式處理編譯檢查性異常,所以你只能擷取一個錯誤訊息。
  現在隨著對ListOfNumbers類的熟悉,並且知道異常是在程式中的什麼地方拋出的,那麼你就可以準備把異常處理器編寫到catch塊來處理那些異常。
怎樣拋出異常
  在你能夠捕捉一個異常之前,在程式中的某個地方必須有拋出這個異常的代碼在在。任何代碼都可以拋出異常:它們可以你自己的代碼,也可以是來自於別人所寫的包中的代碼(例如與Java平台一起提供的程式包),或者是Java運行時環境。不管拋出什麼樣的異常,都要使用throw語句把異常拋出。
  你可能已經注意到,Java平台提供了各種的異常類。所有的這些類都是Throwable類的子類,並且它們都允許程式來區分在程式執行期間所發生的各種類型的異常。
  你也可以建立自己的異常類來描述你編寫的類中所發生的問題。實際上,如果你是一個程式包的開發人員,你可能必須建立你自己的異常類的集合,以便於讓你的使用者來區分在你的程式包中發生的錯誤是來自己於Java平台還是其它的包。
  你也可以建立異常鏈,異常鏈在Java Standard Edition 1.4中被引入。更多的資訊,請看"異常鏈"這一節。

"throw"語句
   所有的方法都使用"throw"語句來拋出一個異常。Throw語句需要一個單獨throwable對象,這個對象是任意Throwable類的子類。如下類所示:
throw someThrowableObject;
   讓我們在程式的上下文中來看一下throw語句。下面的pop方法把來自於一個公用堆棧中的一個執行類給刪除。這個方法從堆棧上面的元素,並且返回被刪除的對象。
public Object pop() throws EmptyStackException {
    Object obj;
    if (size == 0) {
        throw new EmptyStackException();
    }
    obj = objectAt(SIZE - 1);
    setObjectAt(SIZE - 1, null);
    size--;
    return obj;
}
   pop方法檢查堆棧上是否有元素。如果堆棧是空的(也就是說它的尺寸等於0),pop方法就會執行個體化一個新的EmptyStackException對象(它是java.util中的一個成員),並且拋出它。在這章的後面一節會解釋怎樣建立自己的異常類。對於現在,你所需要記住的是你只能拋出繼承於 java.lang.Throwable類的對象。
注意,pop方法的聲明中包含了一個throws子句。EmptyStackException是一個檢查性異常,並且pop方法沒有捕捉這個異常。因此,這個方法必須使用throws子名來聲明它所拋出的異常的類型。

Throwable 類和它的子類

  繼承Throwable類的對象包括直接子類(直接繼承於Throwable類的對象)和間接子類(繼承於Throwable類的子類的對象)。說明了Throwable類的層次關係和最主要的一些子類。象你看到的一樣,Throws有兩個直接的子類:Error類和Exception類。

 

 

Error類
   當在Java虛擬機器中發生動態串連失敗或其它的定位失敗的時候,Java虛擬機器拋出一個Error對象。典型的簡易程式不捕獲或拋出Errors對象。
Exception類
   大多數程式都拋出或捕獲衍生於Exception類的對象。一個異常表明發生了一個問題,但它不是嚴重的系統問題。你編定的大多數程式將會拋出或捕獲Exceptions對象(而不是Errors對象)。
   在Java平台中Exception類有許多已經定義了的子類。這些子類說明所發生的異常的各種類型。例如,IllegalAccessException異常類說明了不能找到一個特殊的方法;NegativeArraySizeException異常類說明程式試圖建立一個帶有負尺寸的數組。
   有一個特殊的Exception子類:RuntimeException。這個子類是在程式運行期間在Java虛擬機器內部所發生的異常。例如 NullPointerException類就是一個運行時異常類,在一個方法試圖通過一個null引用來訪問一個對象的成員時會發生這個異常。在 Unchecked Exceptions---The Controversy這一節中,我們會討論為什麼典型的程式不應該拋出運行時異常或RuntimException類的子類異常對象。

有爭議性的未被檢查的異常
   因為Java程式設計語言不要求方法一定要捕獲或列出運行異常或錯誤,所以程式員就可能被誤導,編寫只拋出運行時異常或者使所有的異常子類都繼承於 RuntimException的代碼,這兩種捷徑允許程式員編寫不用為編譯錯誤而操心的代碼,並且也不費神去指定或捕獲任何異常。儘管這種方法看上去對程式員很方便,但它迴避了捕獲或指定必要的東西的意圖,並且可能使使用你的類的程式員發生錯誤。
   為什麼設計者決定強制一個方法指定所有的在它的範圍內可能被拋出的未檢查異常呢?被一個方法拋出的任何異常都是方法公用編程介面的一部分。方法的調用者必須知道有關這個方法所拋出的異常,以便他們能夠針對這些異常決定做什麼。這些異常是編寫方法的介面差不多,有它們的參數和傳回值。
   接下來你的問題可能是:如果它是這麼好的說明了一個方法的API,包括它能拋出的異常,那麼為什麼不也指定運行時異常呢?運行時異常描述的問題是一個設計問題的結果,並且,API的客戶代碼不能期望從出錯的地方來恢複程式執行或用一些方法來處理它們。這些問題包括演算法異常(例如被零除),指標異常(例如通過一個空的引用來訪問一個對象),以及索引異常(例如試圖通過一個越界的索引來訪問一個數組)。運行時異常可能在程式的任何地方發生,並且在一個典型的程式中可能有很多,因此,在每個方法中不得不添加運行異常來降低程式的透明度,這樣,編譯器不要求你指定或捕獲運行時異常(儘管你可以)。
   拋出運行時異常(RuntimeException)的一個公用案例就是在使用者調用了一個錯誤的方法的時候。例如,一個方法檢查它的參數是否有效,如果一個參數是空(null),那麼這個方法就可能拋出一個NullPointerException異常,這是一個不檢查異常。
   一般來說,不拋出運行時異常(RuntimeException)或不建立一個運行時異常(RuntimeException)的子類的原因是:人你不想為指定你的方法所能拋出的異常而操心。
   一個使用異常的方針是:如果客戶能夠被期望從一個異常中得到恢複,那麼就要使用檢查性異常。如果一個客戶對於從異常中恢複的程式不能做任何事,那麼就可以使用不檢查性異常。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.