1. 程式人生 > >Java異常處理與詳解問題合集

Java異常處理與詳解問題合集

Java異常處理與詳解 

作者:華

日期:2018年5月30日

一次考試考到Java自定義異常,沒有做出來,只是簡單地瞭解了一下,為了鞏固知識,就從各大網站總結了關於Java異常的處理解釋來加深自己的印象。(全部文字雖有雷同但都是親自手打無複製)


Java異常的意義:

異常就是可預測但是又沒辦法消除的一種錯誤。所以程式設計師為了在程式當中不發生這樣的錯誤會將容易發生異常的程式碼用try catch進行處理,或者通過throws將異常向上丟擲,由上一級進行接收並處理。如果發生異常而不去處理,會導致程式中斷,也就是程式無法繼續執行。


Java異常的分類和結構圖:

Java

標準庫內建了一些通用的異常,這些類以Throwable為頂層父類。


Throwable又派生出Error類和Exception類。

Error:錯誤,錯誤代表JVM本身的錯誤。Java 程式通常不捕獲錯誤。錯誤一般發生在嚴重故障時,它們在Java程式處理的範疇之外。

Exception:異常,java異常處理肯定就是異常才是主要要掌握的內容,代表程式執行時傳送的各種不可期望的事件,可以被Java異常處理機制使用,表示程式本身處理的異常。


Javac將異常類分為兩類,不檢查異常和檢查異常:

RuntimeException也稱為unchecked exception(

不檢查異常),非RuntimeException也稱為checked exception(檢查異常),它們之間的區別可以望文生義。 RuntimeException 是那些可能在 Java 虛擬機器正常執行期間丟擲的異常的超類。Java編譯器不去檢查它,也就是說,當程式中可能出現這類異常時,即使沒有用try...catch語句捕獲它,也沒有用throws字句宣告丟擲它,還是會編譯通過,這種異常可以通過改進程式碼實現來避免。

檢查異常就是說程式中遇到這種異常的時候,程式需要對這種異常進行處理,檢查異常的例子有:IOException, SQLException,ClassNotFoundException

等等。對於檢查異常,處理方式有三種:

1. 採用try...catch...finally

2. 直接throw給上層呼叫

3. 對該異常進行捕獲,然後將它封裝成自定義的Exception,然後再throw給上層呼叫。


Java異常處理機制:

對於可能可能出現異常的程式碼,有兩種處理辦法:

第一.  在方法中用try...catch語句捕獲並處理異常,catach語句可以有多個,用來匹配多個異常。


InputStream是一個io異常,所以需要處理,可以用try{}(){}來處理,也可以丟擲異常,現在來說說丟擲異常throws。

 

第二. 對於處理不了的異常或者要轉型的異常,在方法的宣告處通過throws語句丟擲異常。


可以看到處理Socket服務端的IO異常有兩種方式,一種throws和try/catch。

 

處理後就將IOException丟擲給下一個需要呼叫這個name1方法的方法。如果一直不呼叫最終會拋給Java虛擬機器處理,所以不建議使用丟擲異常。


從上面這張圖片可以看出,如果方法name呼叫name1還是需要處理異常。

 

finally

finally塊不管異常是否發生,只要對應的try執行了,則它一定也執行。只有一種方法讓finally塊不執行:System.exit()。因此finally塊通常用來做資源釋放操作:關閉檔案,關閉資料庫連線等等。

良好的程式設計習慣是:在try塊中開啟資源,在finally塊中清理釋放這些資源。

需要注意的地方:

1、finally塊沒有處理異常的能力。處理異常的只能是catch塊。

2、在同一try…catch…finally塊中 ,如果try中丟擲異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。如果沒有catch塊匹配,則先執行finally,然後去外面的呼叫者中尋找合適的catch塊。

3、在同一try…catch…finally塊中 ,try發生異常,且匹配的catch塊中處理異常時也丟擲異常,那麼後面的finally也會執行:首先執行finally塊,然後去外圍呼叫者中尋找合適的catch塊。

下面用程式碼呈現出finally塊的使用。



自定義異常:

如果要自定義異常,則擴充套件Exception即可,因此這樣的自定義異常都屬於檢查異常(checked exception)。如果要自定義非檢查異常,則擴充套件自RuntimeException。

 

按照國際慣例,自定義的異常應該總是包含如下的建構函式:

·        一個無參建構函式

·        一個帶有String引數的建構函式,並傳遞給父類的建構函式。

·        一個帶有String引數和Throwable引數,並都傳遞給父類建構函式

·        一個帶有Throwable 引數的建構函式,並傳遞給父類的建構函式。

 

使用throw人為的讓程式出異常(瞭解)



處理異常時注意事項:

1. 對於執行時異常(RuntimeException類及其子類都被稱為執行時異常)我們不要用try...catch來捕獲處理,而是在程式開發除錯階段,儘量去避免這種異常,一旦發現該異常,正確的做法就會改程序序設計的程式碼和實現方式,修改程式中的錯誤,從而避免這種異常。捕獲並處理執行時異常是好的解決辦法,因為可以通過改進程式碼實現來避免該種異常的發生。

2. (瞭解)異常的鏈化:

在一些大型的,模組化的軟體開發中,一旦一個地方發生異常,則如骨牌效應一樣,將導致一連串的異常。假設B模組完成自己的邏輯需要呼叫A模組的方法,如果A模組發生異常,則B也將不能完成而發生異常,但是B在丟擲異常時,會將A的異常資訊掩蓋掉,這將使得異常的根源資訊丟失。異常的鏈化可以將多個模組的異常串聯起來,使得異常資訊不會丟失。

異常鏈化:以一個異常物件為引數構造新的異常物件。新的異物件將包含先前異常的資訊。這項技術主要是異常類的一個帶Throwable引數的函式來實現的。這個當做引數的異常,我們叫他根源異常(cause)。在JDK1.4以後版本中,Throwable類支援異常鏈機制。Throwable 包含了其執行緒建立時執行緒執行堆疊的快照。它還包含了給出有關錯誤更多資訊的訊息字串。最後,它還可以包含 cause(原因):另一個導致此 throwable 丟擲的 throwable。它也稱為異常鏈 設施,因為 cause 自身也會有 cause,依此類推,就形成了異常鏈,每個異常都是由另一個異常引起的。 
        通俗的說,異常鏈就是把原始的異常包裝為新的異常類,並在新的異常類中封裝了原始異常類,這樣做的目的在於找到異常的根本原因。
        通過Throwable的兩個構造方法可以建立自定義的包含異常原因的異常型別:
Throwable(String message, Throwable cause) 
         構造一個帶指定詳細訊息和 cause 的新 throwable。 
Throwable(Throwable cause)
 
         構造一個帶指定cause 和 (cause==null ? null :cause.toString())(它通常包含類和 cause 的詳細訊息)的詳細訊息的新 throwable。 
getCause()
 
         返回此throwable 的 cause;如果 cause 不存在或未知,則返回 null。
initCause(Throwable cause) 
         將此throwable 的 cause 初始化為指定值。

        在Throwable的子類Exception中,也有類似的指定異常原因的構造方法:
Exception(String message, Throwable cause) 
         構造帶指定詳細訊息和原因的新異常。 
Exception(Throwable cause)
 
         根據指定的原因和 (cause==null ? null : cause.toString()) 的詳細訊息構造新異常(它通常包含 cause 的類和詳細訊息)。 
因此,可以通過擴充套件Exception類來構造帶有異常原因的新的異常類。

3. 避免過大的try塊,不要把不會出現異常的程式碼放到try塊裡面,儘量保持一個try塊對應一個或多個異常。

4.細化異常的型別,不要不管什麼型別的異常都寫成Excetpion
5.catch
塊儘量保持一個塊捕獲一類異常,不要忽略捕獲的異常,捕獲到後要麼處理,要麼轉譯,要麼重新丟擲新型別的異常。

6.不要把自己能處理的異常拋給別人。

7.不要用try...catch參與控制程式流程,異常控制的根本目的是處理程式的非正常情況。

8.當子類重寫父類的帶有 throws宣告的函式時,其throws宣告的異常必須在父類異常的可控範圍內——用於處理父類的throws方法的異常處理器,必須也適用於子類的這個帶throws方法 。這是為了支援多型。

9.對於finally語句塊

·        不要在fianlly中使用return。

·        不要在finally中丟擲異常。

·        減輕finally的任務,不要在finally中做一些其它的事情,finally塊僅僅用來釋放資源是最合適的。

·        將盡量將所有的return寫在函式的最後面,而不是try … catch … finally中。

 

Java 根據各個類庫也定義了一些其他的異常,下面的表中列出了 Java 的非檢查性異常。

下面的表中列出了 Java 定義在 java.lang 包中的檢查性異常類

 

這裡有六道關於Java異常的面試題

https://www.cnblogs.com/gaoweixiao99/p/4905860.html

參考資料:http://blessht.iteye.com/blog/908286http://www.oschina.net/translate/10-exception-handling-best-practices-in-java-programming

http://blog.csdn.net/snow_fox_yaya/article/details/1823205

http://www.iteye.com/topic/72170

http://www.blogjava.net/gdws/archive/2010/04/25/319342.html

http://www.2cto.com/kf/201403/284166.html

http://www.iteye.com/topic/857443

http://developer.51cto.com/art/200808/85625.htm

http://www.cnblogs.com/JavaVillage/articles/384483.html

http://tech.e800.com.cn/articles/2009/79/1247105040929_1.html

http://blog.csdn.net/zhouyong80/article/details/1907799

http://blog.csdn.net/luoweifu/article/details/10721543