異常的捕獲及處理

異常:異常是指中斷程序正常執(zhí)行的一種指令流

?在JAVA程序中一旦出現(xiàn)了異常,而程序又沒(méi)有及時(shí)處理的情況下穆端,那么程序會(huì)中斷執(zhí)行袱贮。

例如,觀察以下的代碼:

public class Demo22{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?System.out.println("i / j = " + (i / j)) ;?à?此段代碼出現(xiàn)了異常

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?以上代碼編譯的時(shí)候不存在任何的問(wèn)題体啰,那么執(zhí)行時(shí)攒巍,出錯(cuò)了荒勇,打印內(nèi)容如下:

---------?計(jì)算開(kāi)始?---------

Exception in thread "main" java.lang.ArithmeticException: / by zero

?at Demo22.main(Demo22.java:6)

?整個(gè)程序,在出現(xiàn)異常的代碼之后不再被執(zhí)行了卷玉,異常之前的程序呢品姓?正確的執(zhí)行了衬潦。

?那么在JAVA中我們所處理的異常都屬于運(yùn)行時(shí)異常,即:執(zhí)行JAVA程序的時(shí)候出現(xiàn)的錯(cuò)誤,那么實(shí)際上對(duì)于JAVA的異常分類應(yīng)該按如下的形式劃分:

?ArithmeticException?à?RuntimeException?à?Exception(往往是要由用戶自己處理的)

?所以對(duì)于異常而言耻瑟,它是一個(gè)統(tǒng)稱谆构,代表了:

?Throwable(可能的拋出)

|-?Exception:表示需要人為處理的異常蔗蹋,指的是程序的錯(cuò)誤?à?因?yàn)槌绦虻腻e(cuò)誤較多妥衣,所以就習(xí)慣了把所有的錯(cuò)誤都統(tǒng)一成為異常蜂筹。

?|- Error:表示JVM錯(cuò)誤,人為不能處理

異常的處理格式如下:

try{

?包含可能出現(xiàn)錯(cuò)誤的代碼段?;

}catch(出錯(cuò)的類型?出錯(cuò)的對(duì)象){

?對(duì)于錯(cuò)誤的處理語(yǔ)句?;

}

?那么使用如上的格式修改之前的代碼口蝠,保證程序可以正確的執(zhí)行完:

public class Demo23{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?System.out.println("i / j = " + (i / j)) ;

?}catch(ArithmeticException e){

?System.out.println("計(jì)算出現(xiàn)了錯(cuò)誤。。。") ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?但是以上的程序依然存在了些小小的問(wèn)題,例如:對(duì)于計(jì)算蹈集,往往應(yīng)該由用戶自己輸入數(shù)據(jù),所以此時(shí)可以通過(guò)接收參數(shù)為其輸入數(shù)據(jù)雇初。代碼如下:

public class Demo24{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?}catch(ArithmeticException e){

?System.out.println("計(jì)算出現(xiàn)了錯(cuò)誤拢肆。。靖诗。") ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?如果現(xiàn)在輸入的內(nèi)容是正確的數(shù)字郭怪,則程序不會(huì)有任何的問(wèn)題,但是既然數(shù)據(jù)是由用戶自己輸入的刊橘,那么肯定會(huì)輸入各種違法的數(shù)據(jù)鄙才。

?存在的問(wèn)題:

?·?不輸入任何參數(shù),出現(xiàn)數(shù)組越界:ArrayIndexOutOfBoundsException

?·?輸入的參數(shù)不是數(shù)字促绵,出現(xiàn)了數(shù)字格式轉(zhuǎn)換錯(cuò)誤:NumberFormatException

?·?輸入的被除數(shù)是0攒庵,出現(xiàn)算術(shù)錯(cuò)誤:ArithmeticException

?在以上的錯(cuò)誤之中嘴纺,只有算術(shù)錯(cuò)誤被處理了,因?yàn)樵诔绦蛏暇邆淞怂阈g(shù)錯(cuò)誤的處理能力浓冒。那么也就意味著栽渴,現(xiàn)在的異常處理并不完善,需要加入更多的處理稳懒,所以需要編寫(xiě)更多的catch熔萧。

?以上的程序修改為:

public class Demo24{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?}catch(ArithmeticException e){

?System.out.println("算術(shù)錯(cuò)誤。僚祷。佛致。"+e) ;

?}

?catch(ArrayIndexOutOfBoundsException e){

?System.out.println("沒(méi)有輸入?yún)?shù)。辙谜。俺榆。"+e) ;

?}

?catch(NumberFormatException e){

?System.out.println("輸入的內(nèi)容不是數(shù)字。装哆。罐脊。"+e) ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?但是會(huì)發(fā)現(xiàn)比較麻煩,因?yàn)楝F(xiàn)在已經(jīng)知道了的是三個(gè)錯(cuò)誤蜕琴,那么對(duì)于很多未知道的錯(cuò)誤呢萍桌?那么此時(shí),就需要分析異常的產(chǎn)生過(guò)程凌简。

?發(fā)現(xiàn)catch中接收的內(nèi)容都是對(duì)象上炎,那么也就意味著,所謂的異常雏搂,就是自動(dòng)產(chǎn)生了一個(gè)異常類的實(shí)例化對(duì)象藕施。一出錯(cuò)就產(chǎn)生。

?對(duì)象有一個(gè)特點(diǎn)凸郑,可以向上自動(dòng)轉(zhuǎn)型裳食,Exception是用戶需要處理的最大異常,那么證明所有的對(duì)象都可以向Exception轉(zhuǎn)換芙沥。

public class Demo25{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?}catch(ArithmeticException e){

?System.out.println("算術(shù)錯(cuò)誤诲祸。。而昨。"+e) ;

?}

?catch(ArrayIndexOutOfBoundsException e){

?System.out.println("沒(méi)有輸入?yún)?shù)救氯。。配紫。"+e) ;

?}

?catch(NumberFormatException e){

?System.out.println("輸入的內(nèi)容不是數(shù)字径密。。躺孝。"+e) ;

?}

?catch(Exception e){

?System.out.println("其他異常享扔。底桂。。"+e) ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

注意:

?如果在程序中出現(xiàn)了多個(gè)catch語(yǔ)句惧眠,則捕獲更粗的catch要放在捕獲更細(xì)的catch之后籽懦。

public class Demo25{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?}catch(Exception e){

?System.out.println("其他異常。氛魁。暮顺。"+e) ;

?}catch(ArithmeticException e){

?System.out.println("算術(shù)錯(cuò)誤。秀存。捶码。"+e) ;

?}catch(ArrayIndexOutOfBoundsException e){

?System.out.println("沒(méi)有輸入?yún)?shù)。或链。惫恼。"+e) ;

?}catch(NumberFormatException e){

?System.out.println("輸入的內(nèi)容不是數(shù)字。澳盐。祈纯。"+e) ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?則編譯的時(shí)候出現(xiàn)了以下的錯(cuò)誤,說(shuō)是許多的異常已經(jīng)被捕獲了叼耙。

Demo25.java:14:?已捕捉到異常?java.lang.ArithmeticException

?catch(ArithmeticException e){

?^

Demo25.java:17:?已捕捉到異常?java.lang.ArrayIndexOutOfBoundsException

?catch(ArrayIndexOutOfBoundsException e){

?^

Demo25.java:20:?已捕捉到異常?java.lang.NumberFormatException

?catch(NumberFormatException e){

?^

3?錯(cuò)誤

?既然所有異常類的對(duì)象都可以向Exception轉(zhuǎn)換腕窥,那么是不是直接使用Exception接收更方便?

public class Demo26{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?System.out.println("***************************") ;

?}catch(Exception e){

?System.out.println(e) ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

?以上是異常處理的一種格式筛婉,實(shí)際上異常處理還有另外一種格式簇爆,就是說(shuō),可以為異常做一個(gè)統(tǒng)一的出口倾贰,不管是否發(fā)生了異常冕碟,都要執(zhí)行此代碼:

try{

?包含可能出現(xiàn)錯(cuò)誤的代碼段?;

}catch(出錯(cuò)的類型?出錯(cuò)的對(duì)象){

?對(duì)于錯(cuò)誤的處理語(yǔ)句?;

}finally{

?不管是否出現(xiàn)異常,都執(zhí)行此代碼?;

}

?代碼如下:

public class Demo27{

?public static void main(String args[]){

?int i = 10 ;

?int j = 0 ;

?System.out.println(" ---------?計(jì)算開(kāi)始?---------") ;

?try{

?i = Integer.parseInt(args[0]) ;

?j = Integer.parseInt(args[1]) ;

?System.out.println("i / j = " + (i / j)) ;

?}catch(Exception e){

?System.out.println(e) ;

?}finally{?à?典型的程序出口

?System.out.println("不管是否存在異常匆浙,此代碼都會(huì)被執(zhí)行。厕妖。首尼。") ;

?}

?System.out.println(" ---------?計(jì)算結(jié)束?---------") ;

?}

};

在異常處理中還有兩個(gè)很重要的關(guān)鍵字

?·?throws:在方法的聲明處使用,表示此方法不處理異常言秸,而交給被調(diào)用處處理软能。

?·?throw:表示人為的拋出一個(gè)異常。

例如:定義一個(gè)數(shù)學(xué)類举畸,里面有一個(gè)除法

class Math{

?//?此代碼有可能發(fā)生問(wèn)題查排,也有可能不發(fā)生問(wèn)題

?//?一旦發(fā)生問(wèn)題,找調(diào)用處抄沮,誰(shuí)調(diào)用的此方法跋核,誰(shuí)去處理

?public int div(int i,int j) throws Exception{

?return i / j ;

?}

};

public class Demo28{

?public static void main(String args[]){

?Math m = new Math() ;

?System.out.println(m.div(10,2)) ;

?}

};

?按規(guī)定來(lái)說(shuō)岖瑰,此方法在調(diào)用的時(shí)候使用異常的捕獲,如果不使用砂代,則編譯時(shí)出現(xiàn)以下的錯(cuò)誤提示:

Demo28.java:11:?未報(bào)告的異常?java.lang.Exception蹋订;必須對(duì)其進(jìn)行捕捉或聲明以便拋出

?System.out.println(m.div(10,2)) ;

?^

1?錯(cuò)誤

?所以對(duì)于調(diào)用有throws聲明的方法,必須使用try…catch:

class Math{

?//?此代碼有可能發(fā)生問(wèn)題刻伊,也有可能不發(fā)生問(wèn)題

?//?一旦發(fā)生問(wèn)題露戒,找調(diào)用處,誰(shuí)調(diào)用的此方法捶箱,誰(shuí)去處理

?public int div(int i,int j) throws Exception{

?return i / j ;

?}

};

public class Demo28{

?public static void main(String args[]){

?Math m = new Math() ;

?try{

?System.out.println(m.div(10,0)) ;

?}catch(Exception e){

?System.out.println(e) ;

?}

?}

};

?問(wèn)智什?既然main方法是一個(gè)方法,那么能不能在主方法上編寫(xiě)throws語(yǔ)句呢丁屎?肯定是可以的

class Math{

?//?此代碼有可能發(fā)生問(wèn)題撩鹿,也有可能不發(fā)生問(wèn)題

?//?一旦發(fā)生問(wèn)題,找調(diào)用處悦屏,誰(shuí)調(diào)用的此方法节沦,誰(shuí)去處理

?public int div(int i,int j) throws Exception{

?return i / j ;

?}

};

public class Demo29{

?public static void main(String args[]) throws Exception{

?Math m = new Math() ;

?System.out.println(m.div(10,0)) ;

?}

};

?觀察錯(cuò)誤的提示:

Exception in thread "main" java.lang.ArithmeticException: / by zero

?at Math.div(Demo29.java:5)

?at Demo29.main(Demo29.java:11)

?可以發(fā)現(xiàn)以上的錯(cuò)誤提示與不使用try…catch效果是一樣的,證明所有的錯(cuò)誤都交給了JVM進(jìn)行處理础爬,實(shí)際上在JAVA中默認(rèn)的處理方式也就是使用JVM完成甫贯。

?throw:表示在程序中人為的拋出一個(gè)異常,而且必須使用try…catch進(jìn)行處理看蚜。

public class Demo30{

?public static void main(String args[]){

?try{

?throw new Exception("我自己樂(lè)意拋叫搁。。供炎。") ;

?}catch(Exception e){

?System.out.println(e) ;

?}

?}

};

?因?yàn)閷?duì)于異常而言渴逻,最終結(jié)果肯定都是拋出一個(gè)異常的實(shí)例化對(duì)象。所以是自己拋還是系統(tǒng)拋都肯定需要進(jìn)行異常的捕獲及處理音诫。

?設(shè)計(jì)一個(gè)除法操作惨奕,在操作之前編寫(xiě):計(jì)算開(kāi)始,在操作之后編寫(xiě)計(jì)算結(jié)束竭钝,中間不管是否出現(xiàn)了錯(cuò)誤梨撞,都要打印這樣兩句話,問(wèn):該如何實(shí)現(xiàn)香罐?

class Math{

?public int div(int i,int j) throws Exception{

?System.out.println(" ========?計(jì)算開(kāi)始?=========") ;

?int temp = 0 ;

?try{

?temp = i / j ;

?}catch(Exception e){

?throw e ;

?}finally{

?System.out.println(" ========?計(jì)算結(jié)束?=========") ;

?}

?return temp ;

?}

};

public class Demo31{

?public static void main(String artgs[]){

?Math m = new Math() ;

??try{

?System.out.println(m.div(1,0)) ;

?}catch(Exception e){

?System.out.println(e) ;

?}

?}

};

?一般而言卧波,對(duì)于throw、throws庇茫、finally往往會(huì)一起使用港粱。

自定義異常:

?一個(gè)類只要繼承了Exception就可以稱為一個(gè)異常類。

class MyException extends Exception{

?public MyException(String msg){

?super(msg) ;

?}

};

public class Demo32{

?public static void main(String args[]){

?try{

?throw new MyException("自己定義玩的旦签。查坪。") ;

?}catch(Exception e){

?System.out.println(e) ;

?}

?}

};

注意點(diǎn):

?·?throw與throws的區(qū)別寸宏?

?|- throw:是人為拋出異常

?|- throws:方法聲明處使用,表示在方法中不處理異常

?·?final與finally

?|- final:定義類咪惠、方法击吱、常量

?|- finally:異常的統(tǒng)一出口

寫(xiě)在最后:

碼字不易看到最后了,那就點(diǎn)個(gè)關(guān)注唄遥昧,只收藏不點(diǎn)關(guān)注的都是在耍流氓覆醇!

關(guān)注并私信我“架構(gòu)”,免費(fèi)送一些Java架構(gòu)資料炭臭,先到先得永脓!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鞋仍,隨后出現(xiàn)的幾起案子常摧,更是在濱河造成了極大的恐慌,老刑警劉巖威创,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件落午,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡肚豺,警方通過(guò)查閱死者的電腦和手機(jī)溃斋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吸申,“玉大人梗劫,你說(shuō)我怎么就攤上這事〗夭辏” “怎么了梳侨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)日丹。 經(jīng)常有香客問(wèn)我走哺,道長(zhǎng),這世上最難降的妖魔是什么聚凹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任割坠,我火速辦了婚禮,結(jié)果婚禮上妒牙,老公的妹妹穿的比我還像新娘。我一直安慰自己对妄,他們只是感情好湘今,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著剪菱,像睡著了一般摩瞎。 火紅的嫁衣襯著肌膚如雪拴签。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天旗们,我揣著相機(jī)與錄音蚓哩,去河邊找鬼。 笑死上渴,一個(gè)胖子當(dāng)著我的面吹牛岸梨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稠氮,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼曹阔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了隔披?” 一聲冷哼從身側(cè)響起赃份,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奢米,沒(méi)想到半個(gè)月后抓韩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鬓长,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年谒拴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痢士。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彪薛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怠蹂,到底是詐尸還是另有隱情善延,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布城侧,位于F島的核電站易遣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嫌佑。R本人自食惡果不足惜豆茫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屋摇。 院中可真熱鬧揩魂,春花似錦、人聲如沸炮温。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至倦挂,卻和暖如春畸颅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背方援。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工没炒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人犯戏。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓送火,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親笛丙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漾脂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Java經(jīng)典問(wèn)題算法大全 /*【程序1】 題目:古典問(wèn)題:有一對(duì)兔子,從出生后第3個(gè)月起每個(gè)月都生一對(duì)兔子胚鸯,小兔子...
    趙宇_阿特奇閱讀 1,875評(píng)論 0 2
  • 【程序1】 題目:古典問(wèn)題:有一對(duì)兔子骨稿,從出生后第3個(gè)月起每個(gè)月都生一對(duì)兔子,小兔子長(zhǎng)到第三個(gè)月后每個(gè)月又生一對(duì)兔...
    開(kāi)心的鑼鼓閱讀 3,325評(píng)論 0 9
  • 50道經(jīng)典Java編程練習(xí)題姜钳,將數(shù)學(xué)思維運(yùn)用到編程中來(lái)坦冠。抱歉哈找不到文章的原貼了,有冒犯的麻煩知會(huì)聲哈~ 1.指數(shù)...
    OSET我要編程閱讀 6,966評(píng)論 0 9
  • JAVA面試題 1哥桥、作用域public,private,protected,以及不寫(xiě)時(shí)的區(qū)別答:區(qū)別如下:作用域 ...
    JA尐白閱讀 1,158評(píng)論 1 0
  • Day01 class 例子{ public static void main(String[] args){ ...
    周書(shū)達(dá)閱讀 1,068評(píng)論 0 0