掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
在編程中異常報錯是不可避免的。特別是在學(xué)習(xí)某個語言初期,看到異常報錯就抓耳撓腮,常常開玩笑說編程1分鐘,改bug1小時。今天就讓我們來看看什么是異常和怎么合理的處理異常吧!

異常與error介紹
下面還是先讓我們來看一下基本概念吧!
? 異常指程序運行過程中出現(xiàn)的非正?,F(xiàn)象,例如用戶輸入錯誤、除數(shù)為零、需要處理的文件不存在、數(shù)組下標越界等。異常機制本質(zhì)就是當(dāng)程序出現(xiàn)錯誤,程序安全退出的機制。在Java的異常處理機制中,引進了很多用來描述和處理異常的類,稱為異常類。異常類定義中包含了該類異常的信息和對異常進行處理的方法。
?Java是采用面向?qū)ο蟮姆绞絹硖幚懋惓5摹L幚磉^程:
讓我們來看看前面所講到的異常類究竟是個什么東西!
其實所有的異常對象都是派生于Throwable類的一個實例。如果內(nèi)置的異常類不能夠滿足需要,還可以創(chuàng)建自己的異常類。所有異常的根類為java.lang.Throwable??纯此募易彘L什么樣。
Throwable類下面主要是兩大門派:Error和Exception。
RuntimeException和 CheckedException異同
首先我們先來看看什么是運行時異常。
這類異常通常是由編程錯誤導(dǎo)致的,所以在編寫程序時,并不要求必須使用異常處理機制來處理這類異常,而是經(jīng)常需要通過增加“邏輯處理來避免這些異?!薄?/p>
比如以下常見的幾種異常:
- int b=0;
- System.out.println(1/b);
- //解決:
- if(b!=0){
- System.out.println(1/b);
- }
- String str = "1234abcf";
- System.out.println(Integer.parseInt(str));
- //解決:
- Pattern p = Pattern.compile("^\\d+$");
- Matcher m = p.matcher(str);
- if (m.matches()) { // 如果str匹配代表數(shù)字的正則表達式,才會轉(zhuǎn)換
- System.out.println(Integer.parseInt(str));
- }
- Animal a=new Dog();
- Cat c=(Cat)a;
- //解決:
- if (a instanceof Cat) {
- Cat c = (Cat) a;
- }
這里再補充兩點,方便大家更好的理解java異常的機制和處理過程。
上面我們講述了什么是運行時異常以及一些處理方式,下面就再來看看什么是已檢查異常吧!
所有不是RuntimeException的異常,統(tǒng)稱為Checked Exception,又被稱為“已檢查異?!?,如IOException、SQLException等以及用戶自定義的Exception異常。 這類異常在編譯時就必須做出處理, 否則無法通過編譯。
通常異常的處理方式有兩種:
下面就來詳細的聊聊吧!
異常的處理
上面已經(jīng)提了,異常處理通常有2種方式。先看看捕獲異常吧。
捕獲異常是通過3個關(guān)鍵詞來實現(xiàn)的:try-catch-finally。用try來執(zhí)行一段程序,如果出現(xiàn)異常,系統(tǒng)拋出一個異常,可以通過它的類型來捕捉(catch)并處理它,最后一步是通過finally語句為異常處理提供一個統(tǒng)一的出口,finally所指定的代碼都要被執(zhí)行。
這個捕獲異常其實也是我們在面試的時候會經(jīng)常碰到的問題。下面我們分別再來對各個部分做一個簡單的提示吧!
(1) try
一個try語句必須帶有至少一個catch語句塊或一個finally語句塊 。當(dāng)異常處理的代碼執(zhí)行結(jié)束以后,不會再回到try語句去執(zhí)行尚未執(zhí)行的代碼。
(2) catch
每個try語句塊可以伴隨一個或多個catch語句,用于處理可能產(chǎn)生的不同類型的異常對象。在此介紹一些常用的方法,這些方法均繼承自Throwable類 。
這里有一個需要特別注意的地方,那就是catch捕獲異常時的捕獲順序:
如果異常類之間有繼承關(guān)系,在順序安排上就需注意。越是頂層的類,越放在下面,再不然就直接把多余的catch省略掉。 也就是說先捕獲子類異常再捕獲父類異常。
(3) finally
finally語句塊中始終都要執(zhí)行,除了遇到了System.exit(0)結(jié)束程序運行。針對這個特性,所以我們通常在finally中關(guān)閉程序塊已打開的資源,比如:關(guān)閉文件流、釋放數(shù)據(jù)庫連接等。
即使try和catch塊中存在return語句,finally語句也會執(zhí)行。是在執(zhí)行完finally語句后再通過return退出。
在這里就有一道非常經(jīng)典的一個面試題。
- 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);
- }
- }
- }
- // 問輸出結(jié)果?
先解釋哈這里存在的玄妙吧!
看了上面的講述,我們都知道了當(dāng)try和catch中有return時,finally仍然會執(zhí)行,所以正常邏輯來說此題的答案應(yīng)該是“jdbk2 2”,但這里存在一個陷阱,那就是:
finally是在return后面的表達式運算后執(zhí)行的(此時并沒有返回運算后的值,而是先把要返回的值保 存起來,不管finally中的代碼怎么樣,返回的值都不會改變,任然是之前保存的值),所以函數(shù)返回值是 在finally執(zhí)行前確定的。因此正確答案應(yīng)該是:“jdbk2 1”。
還有一點需要注意的就是:finally中最好不要包含return,否則程序會提前退出,返回值不是try或catch中保存的返回值。
接下來再來講講聲明異常吧,它相對來說就比較簡單了。
在一些情況下,當(dāng)前方法并不需要處理發(fā)生的異常,而是向上傳遞給調(diào)用它的方法處理。如果一個方法拋出多個已檢查異常,就必須在方法的首部列出所有的異常,之間以逗號隔開。
- public static void readFile(String fileName) throws FileNotFoundException,IOException {
- }
需要注意的地方就是:
自定義異常
我們?yōu)槭裁匆远x異常?還不是因為在程序中,可能會遇到JDK提供的任何標準異常類都無法充分描述清楚我們想要表達的問題。此時我們就可以創(chuàng)建自己的異常類,即自定義異常類。
那我們怎么自定義異常類呢?相信你看了上面的異常類的家族圖應(yīng)該就猜到了。不錯,自定義異常類只需從Exception類或者它的子類派生一個子類即可。如果你繼承Exception類,則為受檢查異常,必須對其進行處理;如果不想處理,可以讓自定義異常類繼承運行時異常RuntimeException類。通常我們自定義異常類應(yīng)該包含2個構(gòu)造器:一個是默認的構(gòu)造器,另一個是帶有詳細信息的構(gòu)造器。這里舉一個例子。
- /**IllegalAgeException:非法年齡異常,繼承Exception類*/
- class IllegalAgeException extends Exception {
- //默認構(gòu)造器
- public IllegalAgeException() {
- }
- //帶有詳細信息的構(gòu)造器,信息存儲在message中
- public IllegalAgeException(String message) {
- super(message);
- }
- }
- public void setAge(int age) throws IllegalAgeException {
- if (age < 0) {
- throw new IllegalAgeException("人的年齡不應(yīng)該為負數(shù)");
- }
- this.age = age;
- }
最后給大家講述一點使用異常機制的建議:
本文授權(quán)轉(zhuǎn)載自公眾號「良許Linux」。良許,世界500強外企Linux開發(fā)工程師,公眾號里分享大量Linux干貨,歡迎關(guān)注!
網(wǎng)站名稱:聊聊Java中的異常及處理
網(wǎng)頁URL:http://uogjgqi.cn/article/cdchoge.html

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流