Java:異常(細節版)

異常類體系

在這裏插入圖片描述
Throwable是所有異常的基類,它有兩個子類:Error和Exception。
Error表示系統錯誤或資源耗盡, 由Java系統自己使用,應用程序不應拋出和處理。比如圖中列出的虛擬機錯誤(VirtualMacheError)及其子類內存溢出錯誤(OutOfMemoryError)和棧溢出錯誤(StackOverflowError)。
Exception表示應用程序錯誤, 它有很多子類,應用程序也可以通過繼承Exception或其子類創建自定義異常,圖中列出了三個直接子類:IOException(輸入輸出I/O異常),SQLException(數據庫SQL異常),RuntimeException(運行時異常)。
RuntimeException(運行時異常)比較特殊,因爲其他異常也是運行時產生的,它表示的實際含義是unchecked exception (未受檢異常),相對而言,Exception的其他子類和Exception自身則是checked exception (受檢異常),Error及其子類也是未受檢異常。

  • 受檢異常:
    受檢異常必須出現在throws語句中,調用者必須處理,Java編譯器會強制這一點,而未受檢異常則沒有這個要求。
    (受檢異常表示程序本身沒問題,但由於I/O、網絡、數據庫等其他不可預測的錯誤導致的異常,調用者應該進行適當處理。)

  • 未受檢異常:
    未受檢異常表示編程的邏輯錯誤,比如空指針異常。
    (出現這種異常,程序員應該檢查程序代碼的bug而不是想辦法處理這種異常。)

自定義異常:

除了Java API中定義的異常類,我們也可以自己定義異常類,一般通過繼承Exception或者它的某個子類,如果父類是RuntimeException或它的某個子類,則自定義異常也是未受檢異常;如果是Exception或Exception的其他子類,則自定義異常是受檢異常。

finally:
  • 如果沒有異常發生,在try內的代碼執行結束後執行。
  • 如果有異常發生且被catch捕獲,在catch內的代碼執行結束後執行。
  • 如果有異常發生但沒被捕獲,則在異常被拋給上層之前執行。

拓展:由於finally的這個特點,它一般用於釋放資源,如數據庫連接、文件流等。

finally細節:

如果在try或者catch語句內有return語句,則return語句在finally語句執行結束後才執行,但finally並不能改變返回值。
看如下代碼:

    public static int test() {
        int ret = 0;
        try {
            return ret;
        }finally {
            ret = 2;
        }
    }

這個函數的返回值是0,而不是2。
實際的執行過程是:在執行到try內的return ret;語句前,會先將返回值ret保存在一個臨時變量中,然後才執行finally語句,最後try再返回那個臨時變量,finally中對ret的修改不會被返回。

如果在finally中也有return語句呢?
try和catch內的return會丟失,實際會返回finally中的返回值。finally中有return不僅會覆蓋try和catch內的返回值,還會掩蓋try和catch內的異常,就像異常沒有發生一樣,比如說:

    public static int test() {
        int ret = 0;
        try {
            int a = 5/0;
            return ret;
        }finally {
            return 2;
        }
    }

以上代碼中,5/0會觸發ArithmeticException,但是finally中有return語句,這個方法就會返回2,而不再向上傳遞異常了。

finally中不僅return語句會掩蓋異常,如果finally中拋出了異常,則原異常就會被掩蓋,看下面代碼:

    public static int test() {
        try {
            int a = 5/0;
        }finally {
            throw new RuntimeException("hello world");
        }
    }

finally中拋出了RuntimeException,則原異常ArithmeticException就丟失了。

所以,一般而言,爲避免混淆,應該避免在finally中使用return語句或者拋出異常,如果調用的其他代碼可能拋出異常,則應該捕獲異常並進行處理。

throw:

throw代表異常退出;就是拋出異常,它會觸發Java的異常處理機制。

throws:

throws跟在方法的括號後面,可以聲明多個異常,以逗號分隔。這個聲明的含義是說,我這個方法內可能拋出這些異常,我沒有進行處理,至少沒有處理完,調用者必須進行處理。
這個聲明沒有說明具體什麼情況會拋出什麼異常,作爲一個良好的實踐,應該將這些信息用註釋的方式進行說明,這樣調用者才能更好的處理異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章