Java 異常機制(也許是全網最獨特視角) 一、Java中的“異常“指什麼 什麼是異常 一句話簡單理解:異常是程式運行中的一些異常或者錯誤。 (純字面意思) Error類 和 Exception類 Java中“萬物皆對象”,異常也不例外, Java把異常當做對象來處理,並將異常分為兩大類——Erro ...
Java 異常機制(也許是全網最獨特視角)
一、Java中的“異常“指什麼
-
什麼是異常
一句話簡單理解:異常是程式運行中的一些異常或者錯誤。
(純字面意思)
-
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)
三、自定義異常
- 如果Java提供的內置異常類型不能滿足程式設計的需求,我們可以自定義異常類,只需要繼承Exception類或者它的子類,以上異常機制對自定義的異常類同樣適用。
呼,終於寫完咯!人生第一篇博客,歡迎各路大佬指正!
此後會持續更新學習筆記,每一篇都會用心去寫去感悟。
原創聲明:本文完全為作者蘭勃基尼原創,轉載請聲明並附上原文鏈接https://www.cnblogs.com/ForJoy/p/16452920.html。作者各平臺用戶名如下
知乎:我求知若渴呀
博客園:蘭勃基尼_CodeJoy
CSDN:蘭勃基尼_CodeJoy