java開發(fā)兩年潭苞!這些異常處理的方式你得知道忽冻,不然你憑什么漲薪!

前言

異常是在程序中導(dǎo)致程序中斷運(yùn)行的一種指令流此疹,當(dāng)異常發(fā)生時(shí)甚颂,程序?qū)⒅苯又袛啵辉賵?zhí)行后續(xù)的任何操作秀菱!
示例:兩數(shù)相除振诬,若不處理任何異常,則只有在正確輸入兩個(gè)數(shù)字時(shí)衍菱,才能顯示出運(yùn)算結(jié)果赶么。

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("請(qǐng)輸入第1個(gè)數(shù)字:");
        String text1 = scanner.nextLine();
        int x1 = Integer.parseInt(text1);
        System.out.println("請(qǐng)輸入第2個(gè)數(shù)字:");
        String text2 = scanner.nextLine();
        int x2 = Integer.parseInt(text2);
        System.out.println(x1/x2);
    }

當(dāng)輸入的內(nèi)容不為數(shù)字時(shí),就會(huì)產(chǎn)生異常(NumberFormatException脊串,數(shù)字格式異常):


當(dāng)輸入的內(nèi)容均為數(shù)字辫呻,但除數(shù)為0時(shí)清钥,也會(huì)產(chǎn)生異常(ArithmeticException,算數(shù)運(yùn)算異常):


作為程序員放闺,不要想當(dāng)然的認(rèn)為用戶一定會(huì)嚴(yán)格按照你的要求去輸入內(nèi)容祟昭,如果他們某一步輸入出現(xiàn)錯(cuò)誤,則整個(gè)程序都會(huì)中斷怖侦,所以一定要對(duì)異常進(jìn)行處理篡悟!以下是異常處理后的代碼:

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int x1;
        while (true) {
            System.out.println("請(qǐng)輸入第1個(gè)數(shù)字:");
            String text1 = scanner.nextLine();
            try {
                x1 = Integer.parseInt(text1);
                break;
            } catch (NumberFormatException e) {
                System.out.println("輸入有誤,請(qǐng)輸入數(shù)字匾寝!");
            }
        }
        int x2;
        while (true) {
            System.out.println("請(qǐng)輸入第2個(gè)數(shù)字:");
            String text2 = scanner.nextLine();
            try {
                x2 = Integer.parseInt(text2);
                break;
            } catch (NumberFormatException e) {
                System.out.println("輸入有誤搬葬,請(qǐng)輸入數(shù)字!");
            }
        }
        try {
            System.out.println(x1/x2);
        } catch (ArithmeticException e) {
            System.out.println("除數(shù)不能為0艳悔!");
        }
    }

當(dāng)輸入的內(nèi)容不為數(shù)字時(shí)急凰,提示輸入有誤,并提示重新輸入:


當(dāng)除數(shù)為0時(shí)猜年,提示除數(shù)不能為0:


這抡锈,就叫異常處理。

try-catch

如果要想對(duì)異常進(jìn)行處理乔外,則必須采用標(biāo)準(zhǔn)的處理格式企孩,處理格式語(yǔ)法如下:

try {
    // 有可能發(fā)生異常的代碼段
} catch(異常類型1 對(duì)象名1) {
    // 異常的處理操作
} catch(異常類型2 對(duì)象名2) {
    // 異常的處理操作
} ...
finally {
    // 異常的統(tǒng)一出口
}

處理流程:

1.一旦產(chǎn)生異常,則系統(tǒng)會(huì)自動(dòng)產(chǎn)生一個(gè)異常類的實(shí)例化對(duì)象袁稽;
2.那么勿璃,此時(shí)如果異常發(fā)生在try語(yǔ)句,則會(huì)自動(dòng)找到匹配的catch語(yǔ)句執(zhí)行推汽,如果沒有在try語(yǔ)句中补疑,則會(huì)將異常拋出;
3.所有的catch根據(jù)方法的參數(shù)匹配異常類的實(shí)例化對(duì)象歹撒,如果匹配成功莲组,則表示由此catch進(jìn)行處理,

finally:

在進(jìn)行異常的處理之后暖夭,在異常的處理格式中還有一個(gè)finally語(yǔ)句锹杈,那么此語(yǔ)句將作為異常的統(tǒng)一出口,不管是否產(chǎn)生了異常迈着,最終都要執(zhí)行此段代碼竭望。即使沒有發(fā)生異常,在try中使用了return語(yǔ)句裕菠,finally仍然會(huì)執(zhí)行咬清。

異常的體系結(jié)構(gòu)

異常指的是Exception,Exception類,在Java中存在一個(gè)父類Throwable(可能的拋出)
Throwable存在兩個(gè)子類:
1.Error:表示的是錯(cuò)誤旧烧,是JVM發(fā)出的錯(cuò)誤操作影钉,只能盡量避免,無(wú)法用代碼處理掘剪。
2.Exception:一般表示所有程序中的錯(cuò)誤平委,所以一般在程序中將進(jìn)行try…catch的處理。
其中Exception包括以下兩種夺谁,它們的處理方式相同:
1.受檢異常:
當(dāng)程序?qū)懞煤罅猓幾g器會(huì)自動(dòng)對(duì)所寫代碼進(jìn)行檢測(cè),如果有問題予权,代碼將會(huì)飄紅線。
例如:SQLException浪册、IOException扫腺、ClassNotFoundException等。
2.非受檢異常:
即運(yùn)行時(shí)異常(RunntimeException)村象,編譯器無(wú)法對(duì)所寫代碼異常進(jìn)行檢測(cè)笆环,程序?qū)⒃跁?huì)在運(yùn)行時(shí)報(bào)錯(cuò)。
例如:NullPointException厚者、ArithmethicException躁劣、ClassCastException、ArrayIndexOutOfBundException等库菲。

多異常捕獲的注意點(diǎn):

1.捕獲更粗的異常不能放在捕獲更細(xì)的異常之前账忘。
2.如果為了方便,則可以將所有的異常都使用Exception進(jìn)行捕獲熙宇。

特殊的多異常捕獲寫法:

catch(異常類型1 | 異常類型2 對(duì)象名) {
    //表示此塊用于處理異常類型1 和 異常類型2 的異常信息
}

RuntimeExcepion與Exception的區(qū)別:

Integer類:public static int parseInt(String text)throws NumberFormatException
此方法拋出了異常鳖擒,但是使用時(shí)卻不需要進(jìn)行try…catch捕獲處理,原因:
因?yàn)镹umberFormatException并不是Exception的直接子類烫止,而是RuntimeException的子類蒋荚,只要是RuntimeException的子類,則表示程序在操作的時(shí)候可以不必使用try…catch進(jìn)行處理(不飄紅線)馆蠕,如果有異常發(fā)生期升,則由JVM進(jìn)行處理。當(dāng)然互躬,也可以通過try…catch處理播赁。

throws關(guān)鍵字

在程序中異常的基本處理已經(jīng)掌握了,但是隨異常一起的還有一個(gè)稱為throws關(guān)鍵字吼渡,此關(guān)鍵字主要在方法的聲明上使用行拢,表示方法中不處理異常,而交給調(diào)用處處理。
格式:

返回值 方法名稱()throws Exception {
}

throw關(guān)鍵字

throw關(guān)鍵字表示在程序中人為的拋出一個(gè)異常舟奠,因?yàn)閺漠惓L幚頇C(jī)制來看竭缝,所有的異常一旦產(chǎn)生之后,實(shí)際上拋出的就是一個(gè)異常類的實(shí)例化對(duì)象沼瘫,那么此對(duì)象也可以由throw直接拋出抬纸。
代碼:

 throw new Exception("");

自定義異常類(了解)

編寫一個(gè)類,繼承Exception耿戚,并重寫一參構(gòu)造方法湿故,即可完成自定義受檢異常類型。
編寫一個(gè)類膜蛔,繼承RuntimeExcepion秩霍,并重寫一參構(gòu)造方法溯泣,即可完成自定義運(yùn)行時(shí)異常類型。
例如:

class MyException extends Exception { // 繼承Exception,表示一個(gè)自定義異常類
    public MyException(String msg) {
        super(msg); // 調(diào)用Exception中有一個(gè)參數(shù)的構(gòu)造
    }
}

自定義異车猓可以做很多事情搭综, 例如:

class MyException extends Exception {
    public MyException(String msg) {
        super(msg);
        //在這里給維護(hù)人員發(fā)短信或郵件疮方, 告知程序出現(xiàn)了BUG充边。
    }
}

異常處理常見面試題

1.try-catch-finally中哪個(gè)部分可以省略?

答:catch和finally可以省略其中一個(gè)蘑辑,catch和finally不能同時(shí)省略洋机。
注意:格式上允許省略catch塊,但是發(fā)生異常時(shí)就不會(huì)捕獲異常了洋魂,在開發(fā)中也不會(huì)這樣去寫代碼绷旗。

2.try-catch-finally中,如果catch中return了副砍,finally還會(huì)執(zhí)行嗎刁标?

答:finally中的代碼會(huì)執(zhí)行。
執(zhí)行流程:
1.先計(jì)算返回值址晕,并將返回值存儲(chǔ)起來膀懈,等待返回;
2.執(zhí)行finally代碼塊谨垃;
3.將之前存儲(chǔ)的返回值返回出去启搂。
需注意:
1.返回值是在finally運(yùn)算之前就確定了,并且緩存了刘陶,不管finally對(duì)該值做任何的改變胳赌,返回的值都不會(huì)改變。
2.finally代碼中不建議包含return匙隔,因?yàn)槌绦驎?huì)在上述的流程中提前退出疑苫,也就是說返回的值不是try或catch中的值。
3.如果在try或catch中停止了JVM,則finally不會(huì)執(zhí)行捍掺。例如停電撼短,或通過如下代碼退出:
JVM:System.exit(0);

3.關(guān)于以下代碼的輸出:

public class Student {
    public static void main(String[] args) {
        int studentId = test();
        System.out.println("學(xué)生的學(xué)號(hào)是"+studentId);
    }
    public static int test() {
        int studentId = 1000;
        try {
            return studentId;
        } catch(Exception e) {
            return 0;
        } finally {
            studentId=10;
        }
    }
}

正確答案是:學(xué)生的學(xué)號(hào)是1000
解:首先studentId是1000,然后執(zhí)行到try挺勿,將要return學(xué)號(hào)曲横,此時(shí)會(huì)對(duì)基本數(shù)據(jù)類型變量studentId的值1000進(jìn)行備份,然后執(zhí)行finally不瓶,studentId變?yōu)?0禾嫉,但是這只改變了原有變量的值,備份的值不會(huì)發(fā)生變化蚊丐,最終return的仍然是曾經(jīng)的備份值熙参,即1000。

4.和上題類似的案例:

public class Student {
    public static void main(String[] args) {
        StudentId s = test();
        System.out.println("學(xué)生的學(xué)號(hào)是"+s.studentId);
    }
    public static StudentId test() {
        StudentId s = new StudentId();
        s.studentId = 1000;
        try {
            return s;
        } catch(Exception e) {
            return s;
        } finally {
            s.studentId=10;
        }
    }
    public static class StudentId {
        int studentId;
    }
}

正確答案是:學(xué)生的學(xué)號(hào)是10
解:首先棧內(nèi)存中的s存儲(chǔ)了堆內(nèi)存的地址麦备,堆內(nèi)存中s.studentId初始為1000孽椰,然后執(zhí)行到try,將要return的是堆內(nèi)存的地址泥兰,此時(shí)會(huì)對(duì)地址進(jìn)行備份弄屡,然后執(zhí)行finally题禀,堆內(nèi)存中s.studentId改為10鞋诗,最終備份的地址被return出去,但實(shí)際上地址始終沒有發(fā)生過變化迈嘹,s.studentId的值即為修改后的10削彬。

最后

感謝你看到這里,文章有什么不足還請(qǐng)指正秀仲,覺得文章對(duì)你有幫助的話記得給我點(diǎn)個(gè)贊融痛,每天都會(huì)分享java相關(guān)技術(shù)文章或行業(yè)資訊,歡迎大家關(guān)注和轉(zhuǎn)發(fā)文章神僵!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雁刷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子保礼,更是在濱河造成了極大的恐慌沛励,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炮障,死亡現(xiàn)場(chǎng)離奇詭異目派,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胁赢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門企蹭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事谅摄⊥胶樱” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵螟凭,是天一觀的道長(zhǎng)虚青。 經(jīng)常有香客問我,道長(zhǎng)螺男,這世上最難降的妖魔是什么棒厘? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮下隧,結(jié)果婚禮上奢人,老公的妹妹穿的比我還像新娘。我一直安慰自己淆院,他們只是感情好何乎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著土辩,像睡著了一般支救。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拷淘,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天各墨,我揣著相機(jī)與錄音,去河邊找鬼启涯。 笑死贬堵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的结洼。 我是一名探鬼主播黎做,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼松忍!你這毒婦竟也來了蒸殿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸣峭,失蹤者是張志新(化名)和其女友劉穎宏所,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叽掘,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡楣铁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了更扁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盖腕。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赫冬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溃列,到底是詐尸還是另有隱情劲厌,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布听隐,位于F島的核電站补鼻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雅任。R本人自食惡果不足惜风范,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沪么。 院中可真熱鬧硼婿,春花似錦、人聲如沸禽车。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)殉摔。三九已至州胳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逸月,已是汗流浹背栓撞。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彻采,地道東北人腐缤。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓捌归,卻偏偏與公主長(zhǎng)得像肛响,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惜索,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350