什麼是異常
一句話簡單理解:異常是程式執行中的一些異常或者錯誤。
(純字面意思)
Error類 和 Exception類
Java中「萬物皆物件」,異常也不例外,
Java把異常當做物件來處理,並將異常分為兩大類——Error(錯誤)和Exception(異常),它們都是Throwable類的子類。
這裡看起來可能有點奇怪,什麼叫「把異常分為錯誤和異常兩類」??可以這樣粗暴地理解——異常有兩大類,一類是錯誤異常(Error),另一類是異常異常(Exception)。
至於為什麼這麼奇怪,我覺得既有翻譯的問題,也有Java檔案沒說清楚的問題。(主要是翻譯的鍋)
Oracle的JavaSE官方檔案是這樣說的:
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 class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch.
所以個人見解,我們可以把Throwable這個類翻譯為「事故類 」(單詞problem:問題、狀況、事故),這個「事故類」的物件具有可被丟擲的性質,且」事故類「Throwable有兩個子類「錯誤事故」(Error,對應致命的大事故)和"異常事故"(Exception,對應剩餘可以處理的事故)。
所以Java的「異常機制」這個翻譯很容易誤導人,讓人奇怪什麼叫異常包括錯誤和異常,EXception的異常和「異常機制」的異常,這兩個翻譯衝突了,所以我認為更應該翻譯為Java的「事故機制」。
Error類的常見子類有IOError、AWTError、VirtualMachineError等,
Exception類的常見子類有IOException、RuntimeException等。
Error和Exception的區別
Error通常是災難性的致命錯誤,是程式無法控制和處理的,當出現這類異常時,JVM一般會選擇終止執行緒;而Exception通常情況下是可以被程式處理的,並且在程式中應該儘可能的去處理這類異常。
個人總結:曾經糾結Error和Exception的區別糾結了好久,後來發現根本不用糾結,就當成一樣的東西就好了,都是「意外狀況」,只不過一個嚴重點一個不嚴重點而已。由於Error是嚴重的異常,對於程式已經致命了,所以並不需要捕獲(catch)或者宣告(throws),而Exception屬於不那麼嚴重,還可以「挽救」或者說「預判」的異常,所以可以被捕獲(catch)或者宣告(throws)來做出進一步處理。
例外處理的五個關鍵字——try、catch、finally、throw、throws。
try 和 catch 關鍵字可以捕獲異常。
try/catch 程式碼塊放在異常可能發生的地方,try 程式碼塊中的程式碼會先被執行,catch 語句包含要捕獲異常型別的宣告。當 try 語句中的程式碼發生一個異常時,try 後面的 catch 塊就會被檢查,如果發生的異常是catch語句所宣告的異常型別的範例,則該異常會被傳遞到該 catch 塊並執行catch程式碼塊中的程式碼,類似於傳遞一個引數到方法中。
finally程式碼塊出現在catch程式碼塊之後,無論try程式碼塊中是否發生異常,finally程式碼塊中的程式碼總會被執行。
注意:1、try程式碼塊後必須有catch程式碼塊或者finally程式碼塊;
2、靠上的catch所宣告的異常型別不能是靠下的catc所宣告的異常型別的父類別(如以下程式碼中,e1不是e2的父類別)。
try{
//正常執行的程式碼
}catch(Exception1 e1){
//捕獲到Exception1類的異常後執行的程式碼
//捕獲到的異常被賦值給e1
}catch(Exception2 e2){
//捕獲到Exception2類的異常後執行的程式碼
//捕獲到的異常被賦值給e2
}finally{
//善後程式碼
}
throw 和 throws 關鍵字用於主動丟擲異常。
兩個關鍵字的區別是,throw用於丟擲一個異常,而throws用於宣告方法可能丟擲的異常。
throw只能丟擲一個異常物件,throws可以宣告多個可能發生的異常類。
即一個負責丟擲,一個負責宣告。
注意:1、若方法中有 異常(嚴格來說是檢查異常,詳見後文)丟擲,必須使用throws語句在方法頭處宣告異常,或者在方法體內使用try/catch語句將異常丟擲語句包圍(將throw語句置於try程式碼塊中);
2、若一個方法使用了throws語句宣告異常,則參照此方法的另一個方法必須使用throws語句在方法頭處宣告異常,或者使用try/catch語句將參照此方法的語句包圍(將參照此方法的語句置於try程式碼塊中)
public void test1(){
//使用try/catch語句處理異常
try{
throw new Exception();
}catch(Exception e){
System.out.println("Thers's an exception.")
}
}
public void test2() throws Exception{
//使用throws語句在方法頭處宣告異常
throw new Exception();
}
public void test3() throws Exception{
//參照test2也要宣告異常
test2();
}
public void test4() throws Exception{
//參照test2也要宣告異常
總結:可以這樣理解,throw就是丟擲異常,try/catch就是處理異常,throws就是暫時不處理、交給參照自己的方法處理。
檢查異常(checked exception)和非檢查異常(unchecked exception)
檢查異常:除了Error類及其子類 和 RuntimeException類及其子類,其它的Throwable子類都是檢查異常。
非檢查異常:Error類及其子類 和 RuntimeException類及其子類。
檢查異常是編譯器要求程式必須處置的異常,這種異常的特點是Java編譯器會檢查它是否被捕獲(try/catch)或者宣告(throws),否則編譯不通過。非檢查異常是編譯器不要求強制處理的異常。
public viod test(){
//丟擲Error類物件但並不做處理,編譯也能通過。
throw new Error();
}
public viod test(){
//丟擲RuntimeException類物件但並不做處理,編譯也能通過。
throw new RuntimeException();
}
//Error類及其子類 和 RuntimeException類及其子類 都是非檢查異常,
執行時異常和非執行時異常
執行時異常:RuntimeException類及其子類。
非執行時異常:RuntimeException以外的Exception類及其子類。
其實執行時異常就是 除去Error類的非檢查異常,
如果我們不去處理執行時異常,JVM會接管處理,系統會把異常一直往上層拋,一直到最上層,
最上層丟擲之後,如果丟擲異常線上程中,這個執行緒就會退出,如果丟擲異常在主程式中,整個程式就退出了。
也就是說,如果不對執行時異常進行處理,程式會通過編譯並執行,出現執行時異常後,要麼是執行緒終止,要麼是主程式終止。
public class Draft {
public static void test1(){
throw new RuntimeException();
}
public static void test2(){
test1();
}
public static void main(String[] args) {
test2();
}
}
執行以上程式碼,終端會出現以下結果,
Exception in thread "main" java.lang.RuntimeException
at Draft.test1(Draft.java:3)
at Draft.test2(Draft.java:6)
at Draft.main(Draft.java:9)
呼,終於寫完咯!人生第一篇部落格,歡迎各路大佬指正!
此後會持續更新學習筆記,每一篇都會用心去寫去感悟。