Java異常類層次結構圖

什麼是異常
異常的英文單詞是exception,字面翻譯就是“意外、例外”的意思,也就是非正常情況。事實上,異常本質上是程式上的錯誤,包括程式邏輯錯誤和系統錯誤。比如使用空的引用、數組下标越界、記憶體溢出錯誤等,這些都是意外的情況,背離我們程式本身的意圖。錯誤在我們編寫程式的過程中會經常發生,包括編譯期間和運作期間的錯誤,在編譯期間出現的錯誤有編譯器幫助我們一起修正,然而運作期間的錯誤便不是編譯器力所能及了,并且運作期間的錯誤往往是難以預料的。假若程式在運作期間出現了錯誤,如果置之不理,程式便會終止或直接導緻系統崩潰,顯然這不是我們希望看到的結果。是以,如何對運作期間出現的錯誤進行處理和補救呢?Java提供了異常機制來進行處理,通過異常機制來處理程式運作期間出現的錯誤。通過異常機制,我們可以更好地提升程式的健壯性。
unchecked exception(非檢查異常)
也稱運作時異常(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException。對于運作時異常,java編譯器不要求必須進行異常捕獲處理或者抛出聲明,由程式員自行決定。
checked exception(檢查異常,編譯異常)
也稱非運作時異常(運作時異常以外的異常就是非運作時異常),java編譯器強制程式員必須進行捕獲處理,比如常見的IOExeption和SQLException。對于非運作時異常如果不進行捕獲或者抛出聲明處理,編譯都不會通過。
Throwable
有兩個重要的子類:Exception(異常)和 Error(錯誤),二者都是 Java 異常處理的重要子類,各自都包含大量子類。
Error(錯誤)
是程式無法處理的錯誤,表示運作應用程式中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運作時 JVM(Java 虛拟機)出現的問題。例如,Java虛拟機運作錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的記憶體資源時,将出現 OutOfMemoryError。這些異常發生時,Java虛拟機(JVM)一般會選擇線程終止。這些錯誤表示故障發生于虛拟機自身、或者發生在虛拟機試圖執行應用時,如Java虛拟機運作錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應用程式的控制和處理能力之 外,而且絕大多數是程式運作時不允許出現的狀況。對于設計合理的應用程式來說,即使确實發生了錯誤,本質上也不應該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。
Exception(異常)
是程式本身可以處理的異常。Exception 類有一個重要的子類 RuntimeException。RuntimeException 類及其子類表示“JVM 常用操作”引發的錯誤。例如,若試圖使用空值對象引用、除數為零或數組越界,則分别引發運作時異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
差別
注意:異常和錯誤的差別:異常能被程式本身可以處理,錯誤是無法處理。通常,Java的異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常(編譯器要求必須處置的異常):正确的程式在運作中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須采取某種方式進行處理。
除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明抛出它,否則編譯不會通過。
應該catch什麼
其實隻要是Throwable和其子類都是可以throw和catch的,那麼如果在需要統一處理異常的地方,我們應該catch (Throwable th) 還是 catch (Exception)呢?
這兩種處理的差別在于,catch throwable會把Error和其他繼承Throwable的類捕捉到。而catch Exception隻會捕捉Exception極其子類,捕捉的範圍更小。先不考慮有其他的類繼承了Throwable的情況下,第一種catch相當于比第二種catch多捕捉了把Error和其子類。
那麼究竟Error是否需要捕捉呢?JDK中Error類的的注釋(如下)裡提到過,Error是一種嚴重的問題,應用程式不應該捕捉它。
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a “normal” condition, is also a subclass of Error because most applications should not try to catch it.
A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
Java Lanuage Spec 7 中也提到:Error繼承自Throwable而不是繼承自Exception,是為了友善程式可以使用 “catch (Exception)“來捕捉異常而不會把Error也捕捉在内,因為Exception發生後可以進行一些恢複工作的,但是Error發生後一般是不可恢複的。
The class Error is a separate subclass ofThrowable, distinct from Exception in the class
hierarchy, to allow programs to use the idiom “} catch (Exception e) { ” (§11.2.3)
to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.
已經不難看出,Java本身設計思路就是希望大家catch Exception就足夠了,如果有Error發生,catch了也不會有什麼作用。
Error可以catch嗎? 可以catch了後做些其他處理嗎?
Error是可以catch的,而且也可以向正常Exception一樣被處理,而且就算不捕捉的話也隻是導緻目前線程挂掉,其他線程還是可以正常運作,如果有需要的話捕捉Error之後也可以做些其他處理。但是Error是一種系統内部的錯誤,這種錯誤不像Exception一樣是可能是程式和業務上的錯誤是可以恢複的。
參考連結:
http://blog.csdn.net/hguisu/article/details/6155636
http://www.cnblogs.com/dolphin0520/p/3769804.html
http://doc.okbase.net/foxty/archive/120046.html