天天看點

JAVA異常?

java異常分為兩大類,Checked異常和Runtime異常,Checked異常都是在編譯階段可以被處理的異常。

JAVA異常?

Checked異常和Runtime異常的差別和聯系

Checked異常都是可以被處理的異常,在程式中必須顯式地處理Checked異常,如果沒有處理,那麼編譯就會報錯。而Runtime異常可以不被顯式的處理;

都是Exception的子類,繼承了RuntimeException的就是Runtime異常,其他的就是Checked異常。

常見異常類

列舉幾個常見的運作時異常RuntimeException:

IndexOutOfBoundException:數組越界異常;

NullPointerException:空指針異常;

ClassCastException:類轉換異常;

NumberFormatException:數字格式異常;

ArithmeticException:運算異常。

列舉幾個非運作時異常(Checked異常):

SQLException:SQL異常;

IOException:IO異常;

FileNotFoundException:檔案找不到異常,是IOException的子類;

InterruptedException:中斷異常,一般用在多線程程式設計;

ClassNotFoundException:類找不到。

Error錯誤

Error錯誤一般指與虛拟機相關的問題,如系統崩潰,虛拟機錯誤,動态連結失敗等,這種錯誤無法恢複或不可被捕獲,将導緻應用程式中斷。通常應用程式也無法處理這些錯誤,是以程式中不應該試圖使用catch來捕獲Error對象。在方法定義時,也無需throws Error對象。

Checked異常的使用

前面提到了Checked必須顯式的處理,不然編譯報錯,比如聲明一個檔案輸入流:

這段代碼編譯會報錯

是以必須顯式的處理它,處理Checked異常的方式一般有兩種:

如果知道如何處理,那麼最好使用try…catch...塊處理:

如果不知道如何處理,那麼就在方法中抛出,由上一級調用者處理:

使用throw自行抛出異常

有的時候根據業務需要,我們在程式裡面會自行抛出異常,比如如果讀取的檔案内容為空,我們就認為這是一個異常,這時候我們可以使用throw來主動抛出異常,并且用catch捕獲它:

如果throw抛出的是一個runtime異常,那麼程式可以用try…catch…捕獲,也可以不用理會。

異常鍊處理

在真實的企業級應用中,我們往往不會講底層的異常暴露給上層應用,比如不會把SQL異常暴露到使用者界面上。一是對于使用者而言,看到SQL異常對他們也沒啥幫助,二是對于惡意使用者而言,暴露底層異常不安全。

那麼如何屏蔽底層異常呢?通常的做法是:程式先捕獲原始異常,然後抛出一個新的業務異常,新的業務異常包含了對使用者的提示資訊,這種處理方式成為異常轉譯。下面示範一個建立使用者的程式如何屏蔽底層異常:

可以看到程式把原始異常隐藏起來,僅向上提供必要的異常提示資訊,可以保證底層異常不會擴充到表現層,這完全符合對象的封裝原則。

這種把捕獲一個異常然後抛出另一個異常,并把原始異常資訊儲存下來,是一種典型的鍊式處理,在設計模式中被稱為責任鍊模式。

使用異常的幾個建議

我們使用異常是為了實作幾個目标:

使程式代碼混亂最小化;

捕獲并保留診斷資訊;

通知合适的人員;

采用合适的方式結束異常活動

針對這些目标,我們應該做到:

1、不要過度使用和依賴它:異常很友善,但是不要把正常的邏輯處理都使用異常處理,比如

不要在try裡面寫很多代碼:這樣可能增加異常分析的難度,并且大量的代碼可能需要大量的catch來捕獲不同的異常;

避免使用catch來捕獲所有類型的異常:比如catch(Throwable t)或者catch(Exception e)這樣,對所有異常使用同樣的邏輯處理,不得不寫很多if語句處理不同情況,得不償失,并且這種捕獲方式可能将Error、Runtime等可能導緻程式終止的異常捕獲,進而“壓制”了異常,一些關鍵異常可能被悄悄忽略;

不要忽略捕獲到的異常:catch應該做一些有用的事情,不要為空或者隻列印異常,catch塊為空就是瞞天過海,程式出了錯誤,所有人看不到任何異常,但是程式可能已經壞了!在捕獲到異常的時候,要麼處理它,要麼抛出新異常,要麼向上抛出并在合适的地方處理異常。