您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么處理Java中的異常”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么處理Java中的異常”吧!
異常與error介紹
下面還是先讓我們來看一下基本概念吧!
異常指程序運行過程中出現的非正常現象,例如用戶輸入錯誤、除數為零、需要處理的文件不存在、數組下標越界等。異常機制本質就是當程序出現錯誤,程序安全退出的機制。在Java的異常處理機制中,引進了很多用來描述和處理異常的類,稱為異常類。異常類定義中包含了該類異常的信息和對異常進行處理的方法。
Java是采用面向對象的方式來處理異常的。處理過程:
拋出異常:在執行一個方法時,如果發生異常,則這個方法生成代表該異常的一個對象,停止當前執行路徑,并把異常對象提交給JRE。
捕獲異常:JRE得到該異常后,尋找相應的代碼來處理該異常。JRE在方法的調用棧中查找,從生成異常的方法開始回溯,直到找到相應的異常處理代碼為止。
讓我們來看看前面所講到的異常類究竟是個什么東西!
其實所有的異常對象都是派生于Throwable類的一個實例。如果內置的異常類不能夠滿足需要,還可以創建自己的異常類。所有異常的根類為java.lang.Throwable。看看它的家族長什么樣。
Throwable類下面主要是兩大門派:Error和Exception。
Error是程序無法處理的錯誤,表示運行應用程序中較嚴重問題,系統JVM已經處于不可恢復的崩潰狀態中。例如,說內存溢出和線程死鎖等系統問題。
Exception是程序本身能夠處理的異常。Exception類是所有異常類的父類,其子類對應了各種各樣可能出現的異常事件。 通常Java的異常可分為:RuntimeException 運行時異常CheckedException 已檢查異常下面我們來研究研究這兩個異常。
RuntimeException和 CheckedException異同
首先我們先來看看什么是運行時異常。
這類異常通常是由編程錯誤導致的,所以在編寫程序時,并不要求必須使用異常處理機制來處理這類異常,而是經常需要通過增加“邏輯處理來避免這些異常”。
比如以下常見的幾種異常:
ArithmeticException異常
int b=0; System.out.println(1/b); //解決: if(b!=0){ System.out.println(1/b); }
NumberFormatException異常
String str = "1234abcf"; System.out.println(Integer.parseInt(str)); //解決: Pattern p = Pattern.compile("^\\d+$"); Matcher m = p.matcher(str); if (m.matches()) { // 如果str匹配代表數字的正則表達式,才會轉換 System.out.println(Integer.parseInt(str)); }
ClassCastException異常
Animal a=new Dog(); Cat c=(Cat)a; //解決: if (a instanceof Cat) { Cat c = (Cat) a; }
這里再補充兩點,方便大家更好的理解java異常的機制和處理過程。
在方法拋出異常之后,運行時系統將轉為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適的異常處理器。
運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法并執行。當運行時系統遍歷調用棧而未找到合適的異常處理器,則運行時系統終止。同時,意味著Java程序的終止。
上面我們講述了什么是運行時異常以及一些處理方式,下面就再來看看什么是已檢查異常吧!
所有不是RuntimeException的異常,統稱為Checked Exception,又被稱為“已檢查異常”,如IOException、SQLException等以及用戶自定義的Exception異常。 這類異常在編譯時就必須做出處理, 否則無法通過編譯。
通常異常的處理方式有兩種:
使用“try/catch”捕獲異常
使用“throws”聲明異常。
下面就來詳細的聊聊吧!
異常的處理
上面已經提了,異常處理通常有2種方式。先看看捕獲異常吧。
捕獲異常是通過3個關鍵詞來實現的:try-catch-finally。用try來執行一段程序,如果出現異常,系統拋出一個異常,可以通過它的類型來捕捉(catch)并處理它,最后一步是通過finally語句為異常處理提供一個統一的出口,finally所指定的代碼都要被執行。
這個捕獲異常其實也是我們在面試的時候會經常碰到的問題。下面我們分別再來對各個部分做一個簡單的提示吧!
(1) try
一個try語句必須帶有至少一個catch語句塊或一個finally語句塊 。當異常處理的代碼執行結束以后,不會再回到try語句去執行尚未執行的代碼。
(2) catch
每個try語句塊可以伴隨一個或多個catch語句,用于處理可能產生的不同類型的異常對象。在此介紹一些常用的方法,這些方法均繼承自Throwable類 。
toString ()方法,顯示異常的類名和產生異常的原因。
getMessage()方法,只顯示產生異常的原因,但不顯示類名。
printStackTrace()方法,用來跟蹤異常事件發生時堆棧的內容。
這里有一個需要特別注意的地方,那就是catch捕獲異常時的捕獲順序:
如果異常類之間有繼承關系,在順序安排上就需注意。越是頂層的類,越放在下面,再不然就直接把多余的catch省略掉。 也就是說先捕獲子類異常再捕獲父類異常。
(3) finally
finally語句塊中始終都要執行,除了遇到了System.exit(0)結束程序運行。針對這個特性,所以我們通常在finally中關閉程序塊已打開的資源,比如:關閉文件流、釋放數據庫連接等。
即使try和catch塊中存在return語句,finally語句也會執行。是在執行完finally語句后再通過return退出。
在這里就有一道非常經典的一個面試題。
public class Test { public static void main(String[]args) { System.out.println(new Test().test());; } static int test(){ int x = 1; try{ retun x; }finally{ System.out.print("jdbk"+ ++x); } } } // 問輸出結果?
先解釋哈這里存在的玄妙吧!
看了上面的講述,我們都知道了當try和catch中有return時,finally仍然會執行,所以正常邏輯來說此題的答案應該是“jdbk2 2”,但這里存在一個陷阱,那就是:
finally是在return后面的表達式運算后執行的(此時并沒有返回運算后的值,而是先把要返回的值保 存起來,不管finally中的代碼怎么樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是 在finally執行前確定的。因此正確答案應該是:“jdbk2 1”。
還有一點需要注意的就是:finally中最好不要包含return,否則程序會提前退出,返回值不是try或catch中保存的返回值。
接下來再來講講聲明異常吧,它相對來說就比較簡單了。
在一些情況下,當前方法并不需要處理發生的異常,而是向上傳遞給調用它的方法處理。如果一個方法拋出多個已檢查異常,就必須在方法的首部列出所有的異常,之間以逗號隔開。
public static void readFile(String fileName) throws FileNotFoundException,IOException { }
需要注意的地方就是:
在方法重寫中聲明異常時:子類重寫父類方法時,如果父類方法有聲明異常,那么子類聲明的異常范圍不能超過父類聲明的范圍。
聲明異常我們一般在server層中。在controller層或則數據訪問層一般是捕獲異常。
自定義異常
我們為什么要自定義異常?還不是因為在程序中,可能會遇到JDK提供的任何標準異常類都無法充分描述清楚我們想要表達的問題。此時我們就可以創建自己的異常類,即自定義異常類。
那我們怎么自定義異常類呢?相信你看了上面的異常類的家族圖應該就猜到了。不錯,自定義異常類只需從Exception類或者它的子類派生一個子類即可。如果你繼承Exception類,則為受檢查異常,必須對其進行處理;如果不想處理,可以讓自定義異常類繼承運行時異常RuntimeException類。通常我們自定義異常類應該包含2個構造器:一個是默認的構造器,另一個是帶有詳細信息的構造器。這里舉一個例子。
/**IllegalAgeException:非法年齡異常,繼承Exception類*/ class IllegalAgeException extends Exception { //默認構造器 public IllegalAgeException() { } //帶有詳細信息的構造器,信息存儲在message中 public IllegalAgeException(String message) { super(message); } } public void setAge(int age) throws IllegalAgeException { if (age < 0) { throw new IllegalAgeException("人的年齡不應該為負數"); } this.age = age; }
最后給大家講述一點使用異常機制的建議:
要避免使用異常處理代替錯誤處理,這樣會降低程序的清晰性,并且效率低下。
處理異常不可以代替簡單測試---只在異常情況下使用異常機制。
不要進行小粒度的異常處理---應該將整個任務包裝在一個try語句塊中。
異常往往在高層處理。
感謝各位的閱讀,以上就是“怎么處理Java中的異常”的內容了,經過本文的學習后,相信大家對怎么處理Java中的異常這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。