Java異常處理(上)

  今天咱們來聊聊Java裏的一個小妖精,那就是異常。html

什麼是異常?什麼是異常處理?

  異常嘛,顧名思義就是不正常,(逃),是Java程序運行時,發生的預料以外的事情,它阻止了程序按照程序員的預期正常執行。java

  異常處理,應該說異常處理機制,就是專門用來制服這個小妖精的法寶。Java中的異常處理機制能讓程序在異常發生時,按照代碼的預先設定的異常處理邏輯,針對性地處理異常,讓程序盡最大可能恢復正常並繼續執行,且保持代碼的清晰。程序員

  簡而言之,Java異常處理就是能讓咱們主動迎擊可能到來的異常,並將它們以圓潤的方式處理掉。數據庫

  仍是先來看個小栗子,看看java裏的異常長什麼樣。socket

public class Test {
    public static void main(String args[]){
        int i = 0 / 0;
        System.out.println("i = " + i);
    }
}

  

  別慌別慌,不要看到紅色提示就心裏崩潰只想關掉IDE,來,抓緊個人手,帶你看清「異常」這個磨人的小妖精的真面目(滑稽)。spa

  代碼裏將0做爲了分母,所以程序會發生算術異常,拋出一個異常後,若是沒有任何處理,默認會終止程序,因此後面的打印內容並無輸出。在異常內容裏,有說明異常類型爲:java.lang.ArithmeticException,也就是算術異常,後面跟着的是異常緣由: / by zero,也就是說異常出現的緣由是將0做爲了分母,並且後面還有堆棧信息,指出了異常拋出的位置是在com.frank.chapter16.main.Test.main這個包下,Test類的第11行(這個行數若是跟你想的不同,不要在乎,由於個人代碼開始以前還有一些不可描述的說明信息),由於只有一次方法調用,因此沒有很長的堆棧信息,看起來也很簡潔明瞭。指針

  因此你看,其實異常也沒那麼可怕吧,不只給了異常緣由,還告訴了你這個bug是出在第幾行,因此好好利用它,能夠幫助你寫出更難以發現的bug,呸,說錯了,能夠幫助你更容易找到bug(手動滑稽)。code

  若是不但願拋出異常後程序就結束,而是但願它繼續運行呢?那麼就捕獲它。htm

如何使用異常處理

  咱們來把上面那個栗子改改:blog

public class Test {
    public static void main(String args[]){
        try{
            int i = 0 / 0;
        }catch (Exception e){
            System.out.println("好像發生異常了,可是我無論,我還要繼續運行");
        }
        System.out.println("運行完畢!");
    }
}

  輸出以下:

好像發生異常了,可是我無論,我還要繼續運行
運行完畢!

  好的,很強勢,如今即便拋出了異常,程序也繼續運行了。異常就像是一頭野獸,但你一旦捕獲它,馴服它,就能夠爲你所用,隨心所欲了。

  try...catch...是經常使用的異常處理搭配,若是在try語句塊中發生了異常,若是恰好這個異常被捕獲到了,那麼會直接跳到catch語句塊中,執行catch語句中的代碼,像上面的栗子裏,由於對Exception類進行了捕獲處理,因此當它的子類異常java.lang.ArithmeticException被拋出來的時候,也能捕獲它。關於Exception類的結構層次關係,後面再作詳細介紹。

  還有另一種搭配方式,那就是try...catch...finally,finally語句塊比catch要強勢的多,前面說了catch語句塊必需要捕獲到了特定的Exception纔會執行裏面的代碼,若是catch的是ArithmeticException可是拋出的倒是空指針異常,那就不會被捕獲了,異常也就溜之大吉了。這個時候,finally的優點就展現出來了,無論拋出什麼樣的異常,也不論是否拋出了異常,finally中的代碼都會被執行。因此通常的用法是在finally語句塊裏釋放掉那些須要被釋放的資源,如socket鏈接,關閉io流,關閉數據庫鏈接等等。也就是說通常在finally中收拾try中拋出的爛攤子,心疼一秒finally,果真能者多勞啊。

  固然,try...finally這樣的搭配也是ok的,須要注意的是,當try語句中發生了異常以後,在發生異常處以後的代碼將不會再執行,而是跳到相應的catchu或者finally中去。

public class Test {
    public static void main(String args[]){
        try{
            int i = 0 / 0;
        }catch (NullPointerException e) {
            System.out.println("這裏捕獲空指針異常");
        }catch (ArithmeticException e){
            System.out.println("這裏捕獲算術異常");
        }finally {
            System.out.println("這裏是finally");
        }
        System.out.println("運行完畢!");
    }
}

  輸出以下:

這裏捕獲算術異常
這裏是finally
運行完畢!

  在上面的代碼中,catch語句塊是能夠同時使用多個的,第一個catch語句塊捕獲的是空指針異常,但因爲拋出的是算術異常,因此沒有捕獲住,但被第二個catch捕獲到了,因此第二個catch語句塊中的代碼執行了。異常匹配是按照從上到下的順序進行匹配的,最後才執行finally中的代碼塊。關於try...catch...finally,還有一個頗有趣的return問題,若是三個語句塊裏都有return,最終返回結果會是怎樣呢?這裏作了詳細的說明,http://www.cnblogs.com/mfrank/p/7895660.html 有興趣的話能夠看一看。

  絕大多數狀況下,finally中的代碼都是會被執行的,只有一種狀況下,finally中的代碼不會被執行,那就是在try語句塊中結束掉了虛擬機(如:使用 System.exit(0); )。

  關於異常,還有一個關鍵字須要介紹,那就是throw,使用throw能夠主動拋出一個異常。看到這你也許會一臉懵逼,主動拋出???嫌異常不夠多,湊熱鬧不嫌事大??別急別急,中間必定有什麼誤會,把刀放下,有話好好說。

  throw關鍵字確實是用來拋出異常的,你能夠這樣使用:

public class Test {
    public static void main(String args[]){
        try{
            throw new NullPointerException("據說你很閒,給你拋個異常。");
        }catch (NullPointerException e) {
            System.out.println("這裏捕獲空指針異常,提示內容:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

  輸出以下:

這裏捕獲空指針異常,提示內容:據說你很閒,給你拋個異常。
java.lang.NullPointerException: 據說你很閒,給你拋個異常。
    at com.frank.chapter16.main.Test.main(Test.java:11)

  用throw關鍵字能夠拋出任意類型的異常,固然,你想的話,還有拋Error,至於什麼是Error,已經跟Exception的關係,將在下一篇裏進行講解。暫時不用深究。

  在throw異常的時候,能夠加上拋出異常的緣由,這樣能夠更方便定位問題所在,固然,通常來講不會像栗子中這樣使用的,這裏只是爲了簡單起見。

  到此爲止,異常的上半篇已經講解完畢,在這一篇裏,說明了什麼是異常,什麼是異常處理,以及如何使用異常處理機制。相信你們對這個小妖精有了初步的認識,下一篇中,將會講解Exception家族都有哪些成員,如何使用自定義異常,已經異常處理的實際使用中的正確姿式。歡迎你們繼續關注,以後計劃每週兩篇以上的更新,若是有講解遺漏或者很差的地方,歡迎你們及時指出,共同進步!

相關文章
相關標籤/搜索