天天看點

Java筆記:異常定義分類處理異常機制原則注意事項常見面試題目

在《java程式設計思想》中這樣定義異常:阻止目前方法或作用域繼續執行的問題。異常是java程式設計中不可分割的一部分,如果不了解如何使用它們,那麼我們隻能完成很有限的工作。

異常分為3種:

error - 描述了java運作系統中的内部錯誤以及資源耗盡的情況。應用程式不應該抛出這種類型的對象。如果這種内部錯誤出現,除了通知使用者錯誤發生以及盡力安全的退出程式外,在其他方面是無能為力的。

編譯時異常 exception - 它指出了合理的應用程式想要捕獲的條件。exception又分為兩類:ioexception和runtimeexception。由程式設計導緻的錯誤,會導緻runtimeexception異常。而其他錯誤原因導緻的異常(例如因為i/o錯誤導緻曾經運作正确的程式出錯),都不會導緻runtimeexception異常。

運作時 runtimeexception - 表示運作時異常,不強制要求寫出顯示的捕獲代碼,但如果沒有被捕獲到,則線程會被強制中斷

繼承關系:

從 runtimeexception 衍生出來的異常包括下面的問題:

錯誤的類型轉換

數組越界通路

試圖通路空指針

從 ioexception 衍生出來的異常包括:

試圖從檔案尾後面讀取資料

試圖打開一個錯誤可是的 url

試圖用一個字元串來構造一個 class 對象,而與該字元串對應的類并不存在

異常的好處:

1、将問題進行封裝

2、将正常流程代碼和問題代碼相分離,便于閱讀。

在java應用程式中,異常處理機制為:抛出異常,捕捉異常。

<code>抛出異常</code>:當一個方法出現錯誤引發異常時,方法建立異常對象并傳遞運作時系統,異常對象中包含了異常類型和異常出現時的程式狀态等異常資訊。運作時系統負責尋找處置異常的代碼并執行。

<code>捕獲異常</code>:在方法抛出異常之後,運作時系統将轉為尋找合适的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法抛出的異常類型相符時,即為合适的異常處理器。運作時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合适異常處理器的方法并執行。當運作時系統周遊調用棧而未找到合适的異常處理器,則運作時系統終止。同時,意味着java程式的終止。

任何 java 代碼都可以抛出異常,如:自己編寫的代碼、來自 java 開發環境包中代碼,或者 java 運作時系統。無論是誰,都可以通過 java 的 throw 語句抛出異常。

從方法中抛出的任何異常都必須使用 <code>throws</code> 子句。

捕捉異常通過 <code>try-catch</code> 語句或者 <code>try-catch-finally</code> 語句實作。

編譯時異常exception,給了幾條禁止的原則,他們是:

1)不要直接忽略異常;

2)不要用try-catch包住過多語句;

3)不要用異常處理來處理程式的正常控制流;

4)不要随便将異常迎函數棧向上傳遞,能處理盡量處理。

向上傳播異常:

如果不能用上述恢複措施,就檢查能不能向上傳播,什麼情況下可以向上傳播呢?有多種說法,一種說法是當本方法恢複不了時,這個說法顯然是錯誤,因為上層也不一定能恢複。另外還有兩種說法是:1.當上層邏輯可以恢複程式時;2.當本方法除了列印之外不能做任何處理,而且不确定上層能否處理。這種兩種說法都是正确的,但還不夠,因為也有的情況,明确知道上層恢複不了也需要上層處理,是以我認為正确的做法是:當你認為本異常應該由上層處理時,才向上傳播。

何時選用編譯時異常:

1、如果調用者可以恢複此異常情況

2、如果調用者不能恢複,但能做出有意義的事,如轉譯等。如果你不确定調用者能否做出有意義的事,就别使編譯時異常,免得被抱怨。

3、應盡最大可能使用編譯時異常來代替錯誤碼,這條也是編譯時異常設計的目的。

另外,必須注意使用編譯時異常的目的是為了恢複執行,是以設計異常類的時候,應提供盡量多的異常資料,以便于上層恢複,比如一個解析錯誤,可以在設計的異常類寫幾個變量來存儲異常資料:解析出錯的句子的内容,解析出錯句子的行号,解析出錯的字元在行中的位置。這些資訊可能幫助調用恢複程式。

當使用多個 catch 語句塊來捕獲異常時,需要将父類的 catch 語句塊放到子類型的 catch 塊之後,這樣才能保證後續的 catch 可能被執行,否則子類型的 catch 将永遠無法到達,java 編譯器會報編譯錯誤。

如果 try 語句塊中存在 return 語句,那麼首先會執行 finally 語句塊中的代碼,然後才傳回。

如果 try 語句塊中存在 <code>system.exit(0)</code> 語句,那麼久不會執行 finally 語句塊的代碼了,因為 <code>system.exit(0)</code>會終止目前運作的 jvm。程式在 jvm 終止前結束執行。

1、error和exception有什麼差別

error 表示系統級的錯誤,是java運作環境内部錯誤或者硬體問題,不能指望程式來處理這樣的問題,除了退出運作外别無選擇,它是java虛拟機抛出的。

exception 表示程式需要捕捉、需要處理的異常,是由與程式設計的不完善而出現的問題,程式必須處理的問題

2、運作時異常和一般異常有何不同

java 提供了兩類主要的異常:runtimeexception 和 checkedexception

一般異常(checkedexception)主要是指 io 異常、sql 異常等。對于這種異常,jvm 要求我們必須對其進行 cathc 處理,是以,面對這種異常,不管我們是否願意,都是要 寫一大堆的 catch 塊去處理可能出現的異常。

運作時異常(runtimeexception)我們一般不處理,當出現這類異常的時候程式會由虛拟機接管。比如,我們從來沒有去處理過 nullpointerexception,而且這個異常還是最 常見的異常之一。

出現運作時異常的時候,程式會将異常一直向上抛,一直抛到遇到處理代碼,如果沒有 catch 塊進行處理,到了最上層,如果是多線程就有 thread.run()抛出,如果不是多線程 那麼就由 <code>main.run()</code> 抛出。抛出之後,如果是線程,那麼該線程也就終止了,如果是主程式,那麼該程式也就終止了。

其實運作時異常的也是繼承自 exception,也可以用 catch 塊對其處理,隻是我們一般不處理罷了,也就是說,如果不對運作時異常進行 catch 處理,那麼結果不是線程退出就是 主程式終止。

如果不想終止,那麼我們就必須捕獲所有可能出現的運作時異常。如果程式中出現了異常資料,但是它不影響下面的程式執行,那麼我們就該在catch塊裡面将異常資料舍棄, 然後記錄日志。如果,它影響到了下面的程式運作,那麼還是程式退出比較好些。

3、java 中異常處理機制的原理

jav a通過面向對象的方式對異常進行處理,java 把異常按照不同的類型進行分類,并提供了良好的接口。在 java 中,每個異常都是一個對象,它都是 throwable 或其子類的執行個體。當一個方法出現異常後就會抛出一個異常對象,該對象中包含有異常資訊,調用這個對象的方法可以捕獲到這個異常并對異常進行處理。java 的異常處理是通過5個 關鍵詞來實作的:try、catch、throw、throws、finally。

<code>try</code>:用來指定一塊預防所有異常的程式

<code>catch</code>:緊跟在try後面,用來捕獲異常

<code>throw</code>:用來明确的抛出一個異常

<code>throws</code>:用來标明一個成員函數可能抛出的各種異常

<code>finally</code>:確定一段代碼無論發生什麼異常都會被執行的一段代碼。

4、你平時在項目中是怎樣對異常進行處理的。

1)盡量避免出現 runtimeexception。例如對于可能出現空指針的代碼,帶使用對象之前一定要判斷一下該對象是否為空,必要的時候對 runtimeexception也進行 <code>try catch</code> 處理。

2)進行 <code>try catch</code> 處理的時候要在 catch 代碼塊中對異常資訊進行記錄,通過調用異常類的相關方法擷取到異常的相關資訊。

5、final、finally、finalize的差別

(1)、final 用于聲明變量、方法和類的,分别表示變量值不可變,方法不可覆寫,類不可以繼承

(2)、finally 是異常進行中的一個關鍵字,表示 <code>finally{}</code> 裡面的代碼一定要執行

(3)、finalize 是 object 類的一個方法,在垃圾回收的時候會調用被回收對象的此方法。