在程式運行時,發生了期望之外的情況,它阻止了程式按照程式員的預期正常執行,這就是異常。 對於異常,Java提供了優秀的解決辦法:異常處理機制。常處理機制能讓程式在異常發生時,按照代碼的預先設定的異常處理邏輯,針對性地處理異常,讓程式盡最大可能恢復正常並繼續執行,且保持代碼的清晰。 Java中的異常可 ...
在程式運行時,發生了期望之外的情況,它阻止了程式按照程式員的預期正常執行,這就是異常。
對於異常,Java提供了優秀的解決辦法:異常處理機制。常處理機制能讓程式在異常發生時,按照代碼的預先設定的異常處理邏輯,針對性地處理異常,讓程式盡最大可能恢復正常並繼續執行,且保持代碼的清晰。
Java中的異常可以是函數中的語句執行時引發的,也可以是程式員通過throw語句手動拋出的。只要在Java程式中產生了異常,JVM就會創建一個對象,將異常的具體信息保存到這個對象中,通過throw關鍵字將這個對象拋出去。如果這個函數中書寫了處理異常的代碼,就執行這個代碼;如果沒有,就將這個異常返回給函數的調用者,並結束這個函數。如果函數的調用者書寫了處理異常的代碼,就執行這個代碼;如果沒有,就將異常發生的位置也保存到對象中,然後將對象繼續向上一級拋出。如果一直沒有處理異常的代碼,最終這個對象就會拋給JVM。JVM就會將對象中保存的異常信息輸出到控制台,然後結束程式。
異常的體系和分類:
從圖中可以看到,Throwable類是所有錯誤和異常的頂層父類。
錯誤:Error類及其子類,一般是JVM自身的錯誤(系統錯誤),程式員通過代碼無法處理。因此我們一般要關心能夠通過代碼處理的Exception類及其子類。
異常:Exception類及其子類,一般是程式運行時發生的不被期望的事情。可以被Java異常處理機制處理。
Exception類又分為運行異常類(非檢查異常類)和非運行異常類(可檢查異常類)。
RuntimeExcetion類及其子類是運行異常類(非檢查異常)。它是在程式運行時有解釋器引發的各種異常,可以發生在任何地方且出現頻率很高。因此為了避免巨大的系統資源開銷,編譯器不會對這類異常進行檢查。對於這類異常我們可以編寫代碼處理,也可以不處理。這類異常出現,一般是我們的代碼寫的有問題,可以通過修正代碼來避免。如算術異常(除0)ArithmeticExecption,類型強制轉換錯誤 ClassCastException,空指針異常 NullPointerException,角標越界異常 ArrayIndexOutOfBoundsException等等。
除RuntimeException類及其子類外,Exception類的其他子類都是非運行異常(可檢查異常)。它在編譯的時候就會由編譯器進行檢查。這類異常必須進行異常處理,如果不處理,則編譯不通過。這類異常是由於程式可能被運行在各種未知的環境下,而程式員無法干預用戶如何使用他編寫的程式,於是程式員就應該為這樣的異常時刻準備著。這類異常有SQLException , IOException,ClassNotFoundException 等。
處理異常的方式:
在Java編寫代碼處理可檢查異常時,有兩種處理方式。
1、通過Throws關鍵字聲明可能發生的異常,交給函數的調用者去處理。
2、通過try{ } catch{ } finally { } 語句來捕捉並處理異常。
需要註意的是:
1、當聲明異常時,
如果一個函數中會拋出多個異常,每一個異常都要處理;
也可以聲明一個它們共同的父類;
2、當捕捉異常時,
如果有多個異常,要多次分別捕獲,分別處理;使用多個catch;
如果處理代碼一樣,可以使用一個catch捕獲;
如果同一個try塊下的多個catch異常類型有父子關係,應該將子類異常放在前面,父類異常放在後面,這樣保證每個catch塊都有存在的意義。
finally塊不管異常是否發生,只要對應的try執行了,則它一定也執行。只有一種方法讓finally塊不執行:System.exit()。因此finally塊通常用來做資源釋放操作:關閉文件,關閉資料庫連接等等。
在同一try...catch...finally塊中 ,如果try中拋出異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。如果沒有catch塊匹配,則先執行finally,然後去外面的調用者中尋找合適的catch塊。
在同一try...catch...finally塊中 ,try發生異常,且匹配的catch塊中處理異常時也拋出異常,那麼後面的finally也會執行:首先執行finally塊,然後去外圍調用者中尋找合適的catch塊。
繼承中方法重寫的異常:
子類重寫的函數不能比父類中的函數聲明更多的編譯異常且只能聲明這個異常或者它的子異常;
重寫函數聲明運行時異常,對方法重寫沒有影響。
自定義異常:
在Java中已經已經有了一些異常類來描述程式中常出現的問題。除此之外,我們還可以自定義異常。
步驟:
1、自定義一個異常類,繼承Exception或RuntimeException;
2、給這個類提供一個構造函數,在構造函數中用super調用父類有參函數。