異常

異常就是程序生病了恢筝,不處理異常,程序就會(huì)翹翹料睛,終止運(yùn)行丐箩。對(duì)于異常的方法,一定要加上 @exception 文檔注釋恤煞。子類在重寫父類中的抽象方法時(shí)處理的異常一定要比父類中處理的異常多屎勘,也就是說子類 throws 的異常一定只能比父類 throws 的異常少。說的更直白點(diǎn)居扒,就是兒子一定不能比老子懶概漱,再不濟(jì)也要一樣勤快。只要這樣世界才會(huì)不斷進(jìn)步呢喜喂!

異常通常都是交給控制層來處理的犀概,業(yè)務(wù)層和持久層專注于功能實(shí)現(xiàn),在框架中甚至都不需要自行在控制層手工處理異常了夜惭。這是因?yàn)楫惓5脑O(shè)計(jì)之初就是為了幫助程序員方便處理錯(cuò)誤姻灶,所以對(duì)待異常的原則應(yīng)該是把出現(xiàn)問題和處理問題的地方分隔開來。業(yè)務(wù)層和持久層專注于處理業(yè)務(wù)和數(shù)據(jù)存儲(chǔ)的問題诈茧,異常就全部拋給控制層去處理产喉。

為什么要引入異常機(jī)制?

首先明確一個(gè)大前提敢会,運(yùn)行中的程序是一定無法避免出現(xiàn)問題的曾沈。比如斷電了或者機(jī)器硬件壞了,文件找不到或者斷網(wǎng)了鸥昏。那怎么辦呢塞俱? Java 就提供了異常機(jī)制來處理這類問題,通過異常機(jī)制來保證程序的健壯性和可維護(hù)性吏垮。

Java 提供的異常機(jī)制

問題分為 Error 和 Exception 障涯,比如斷電了或者機(jī)器硬件壞了罐旗,導(dǎo)致程序無法正常運(yùn)行,這類屬于 Error 唯蝶,再厲害的程序員也不可能通過寫代碼解決九秀。比如文件找不到或者斷網(wǎng)了,導(dǎo)致程序無法正常運(yùn)行粘我,這類屬于 Exception 鼓蜒。Exception 又分為編譯異常和運(yùn)行異常。編譯異常通常給用戶一個(gè)良好提示征字,運(yùn)行異常在編寫源代碼的過程中要盡量解決掉都弹。異常的命名應(yīng)該是能夠望文生義的,看到名字就能夠猜出異常它的作用匙姜,無論是 java 標(biāo)準(zhǔn)類庫還是自定義的異常類都應(yīng)該遵循此規(guī)則畅厢,所有東西都應(yīng)該是這樣命名的啊。比如所有的輸入輸出異常都是 IOException 的子類搁料!

java.lang.Throwable

throwable 是一個(gè)形容詞,表示可拋出的意思系羞。繼承于 java.lang.Object 類郭计,是 Error 和 Exception 的直接父類,它提供了異常類的基本功能椒振。異常類繼承層次結(jié)構(gòu)圖如下:

_Throwable.png

既然所以異常類都是繼承自 Throwable 昭伸,那么 Throwable 擁有的數(shù)據(jù)結(jié)構(gòu)對(duì)于每一個(gè)異常類都是存在的。對(duì)于異常類需要知道的數(shù)據(jù)結(jié)構(gòu)有以下幾個(gè)點(diǎn)澎迎。

  • private String detailMessage私有的 String 類型的屬性庐杨,detailMessage 屬性是用來描述異常的一段字符串信息。
  • 至少兩個(gè)構(gòu)造函數(shù)夹供,一個(gè)空構(gòu)造函數(shù)灵份,一個(gè)有參的構(gòu)造函數(shù)來給私有屬性 detailMessage 賦值。
  • public String getMessage()方法哮洽,返回的就是異常類的 detailMessage 屬性填渠。
  • public String toString()Throwable 重寫了其父類 Object 的 toString() 方法,其輸出格式為:異常類名:detailMessage鸟辅。
  • public void printStackTrace()用來打印異常棧的信息氛什,方便跟蹤程序異常信息》肆梗控制臺(tái)中打印異常棧信息的順序是:先從異常拋出處的方法開始枪眉,一路回退到它最開始的調(diào)用方。為什么是這樣子的呢再层?要明白贸铜,任何知識(shí)點(diǎn)都不是孤立的堡纬,他們之間一定能夠建立聯(lián)系萨脑。實(shí)現(xiàn)這個(gè)功能其實(shí)很簡單啊隐轩,每一個(gè)線程都有一個(gè)方法調(diào)用棧渤早,所以在遇到拋出異常方法的時(shí)候,在這個(gè)方法棧里面已經(jīng)積壓了很多方法了鹊杖,邊退棧邊打印調(diào)用棧中方法的信息即可悴灵。理解了這一點(diǎn),就理解了為什么會(huì)先從拋出異常方法處首先打印異常了骂蓖,這不就是退棧的過程嗎?此方法還有另外兩個(gè)重載的方法登下,區(qū)別在于不同的參數(shù),接收不同的輸出流對(duì)象被芳,如下public void printStackTrace(PrintWriter s)public void printStackTrace(PrintStream s)方法

編譯異常

5編譯異常中最常見的就是 IOException 了缰贝,這里也只拿這類異常舉例。編譯異常必須顯示的使用 try catch 進(jìn)行預(yù)處理畔濒,否則編譯階段就不給通過。

這其實(shí)是 java 的一種設(shè)計(jì)思想侵状,因?yàn)槌绦蜻\(yùn)行過程中發(fā)生資源不存在問題的可能性非常大,所以 JDK 類庫設(shè)計(jì)者提供的某些方法或者構(gòu)造方法就顯示的使用 throws 關(guān)鍵字事先聲明不處理某種異常趣兄,強(qiáng)迫調(diào)用這種方法的客戶端程序員對(duì)這類異常進(jìn)行預(yù)處理。

運(yùn)行異常

運(yùn)行異常是在程序運(yùn)行過程中遇到不正常情況艇潭,由 JVM 創(chuàng)建并拋出的異常對(duì)象,如果沒有對(duì)此異常進(jìn)行處理的話闯团,該異常對(duì)象一路被拋到 main() 方法中,JVM 就會(huì)自動(dòng)調(diào)用該異常對(duì)象繼承子 Throwable 的public void printStackTrace()方法打印異常棧信息房交。這種運(yùn)行時(shí)異常是無法在編譯階段檢查出來的伐割,因?yàn)樗耆险Z法規(guī)則候味,只有在程序運(yùn)行時(shí),JVM 才能夠判斷它是否會(huì)出現(xiàn)問題织咧。

比如NullPointerExceptionArithmeticException就是常見的運(yùn)行時(shí)異常類蟆融。運(yùn)行時(shí)異常才是真正讓人感覺到可怕的事情,在編寫程序的過程中粱玲,即使語法上不要求進(jìn)行異常處理,但是最好顯示的去判斷允青,去處理,程序編寫可能顯得比較麻煩颠锉,但是真正出問題了史汗,就會(huì)發(fā)現(xiàn)一切付出都是值得的琼掠。

異常的處理流程

這里拿運(yùn)行異常舉例淹办,編譯異常是同理的恶复。程序運(yùn)行過程中,JVM 發(fā)現(xiàn)不正確情況谤牡,就在 new 出一個(gè)異常對(duì)象,并給它的 detailMessage 屬性賦值翅萤。然后檢查此處是否有 try catch 捕獲了對(duì)應(yīng)的異常對(duì)象,如果有則進(jìn)入到 catch 代碼段套么,如果沒有則查看此方法是否使用 throws 關(guān)鍵字聲明不處理異常培己,如果有則到調(diào)用此方法的方法中進(jìn)行同樣的流程處理。如果都沒有胚泌,JVM 就會(huì)拋出此異常,程序被迫中斷玷室,控制臺(tái)打印出相應(yīng)的異常信息笤受。

捕獲異常的原則是必須要盡可能的細(xì)化敌蜂,catch 代碼塊要呈金字塔鋪開。做更細(xì)致化的異常處理是為了分化問題章喉,便于對(duì)具體問題做具體分析和處理。要想成為一個(gè)好的程序員囊陡,一定要做到這些。

如果在主方法中使用 throws 聲明不處理異常妥色,這只是騙了編譯器遏片,語法上是通過了,但是主方法是 JVM 調(diào)用的吮便,相當(dāng)于還是拋給了 JVM ,該發(fā)生的異常還是會(huì)發(fā)生髓需,程序該中斷還是會(huì)中斷。

throws 和 throw 以及 finally

throws 用在方法聲明后面微渠,后面跟的是一個(gè)或多個(gè)異常類咧擂,表示不處理異常逞盆。throw 用在方法內(nèi)部松申,后面跟的是一個(gè)異常對(duì)象,表明此處拋出一個(gè)異常對(duì)象舅逸。如果一個(gè)方法中 throw 出一個(gè)異常對(duì)象皇筛,此方法就必須用 throws 聲明不處理此異常,那就會(huì)拋給調(diào)用此方法的方法去處理设联∽莆妫或者在此方法內(nèi)部用 try catch 捕獲换团,否則編譯階段都不會(huì)通過。

至于 finally 關(guān)鍵字艘包,設(shè)計(jì)之初的本意是用來關(guān)閉資源的,比如輸入輸出流發(fā)生異常卦尊,在 finally 代碼塊中關(guān)閉資源舌厨。無論程序是否發(fā)生異常,finally 的代碼都會(huì)被執(zhí)行裙椭,這是 Java 的設(shè)計(jì)機(jī)制。

try 中發(fā)生異常揉燃,如果異常被 catch 捕獲,則先執(zhí)行catch 的語句正驻,再執(zhí)行 finally 的語句抢腐。如果異常沒有被捕獲姑曙,會(huì)先執(zhí)行 finally 中的代碼氓栈,再拋出此異常婿着,因?yàn)槿绻葤伋隽水惓#?finally 代碼塊的內(nèi)容就無法執(zhí)行了提完。

finally 簡直太牛了丘侠,即使它前面有 return 語句,也會(huì)等到 fianlly 代碼塊的語句執(zhí)行完了后再返回蜗字,但是如果 finally 有 return 語句脂新,就會(huì)覆蓋之前的語句粗梭,可以利用 return 返回棧的概念分析。實(shí)例代碼如下:

public static int f() {
        try {
            System.out.println("try"+ 5/0);
            return 1;
        }catch(Exception e){
            return 3;
        }finally {
            return 2;
        }
    }//此方法返回 2 

如果 catch 捕獲了相應(yīng)異常断医,但是在處理異常的過程中又發(fā)生了異常,那么此時(shí)本應(yīng)該拋出異常斩启,但是會(huì)先執(zhí)行 finally 代碼塊的內(nèi)容后再拋出異常醉锅。但是如果 finally 代碼塊中有 return 語句,不僅會(huì)覆蓋之前所有的 return 語句硬耍,還會(huì)是的程序就此結(jié)束。之前未來得及處理的異常就這樣被隱藏了此虑。

finally 代碼塊中不要出現(xiàn) return 語句,不要亂寫朦前。上面講到的內(nèi)容只是有可能會(huì)遇到這樣的面試題鹃操,只要知道 finally 中的 return 語句有一個(gè) return 返回棧的概念就可以了,利用這個(gè)概念輔助分析荆隘。

自定義異常類

為什么要使用自定義異常類?Java 異常機(jī)制就是設(shè)計(jì)來處理程序中不正確問題的一種手段晶渠。這些都屬于程序運(yùn)行上的問題燃观,計(jì)算機(jī)是用來解決問題的,在現(xiàn)實(shí)中有很多功能性錯(cuò)誤缆毁,也就是程序運(yùn)行上沒有問題,但是在具體業(yè)務(wù)功能上不符合需求。比如銀行系統(tǒng)中如果用戶取錢大于賬戶余額践啄,這就屬于業(yè)務(wù)功能性錯(cuò)誤沉御。這類問題可以巧妙的利用異常機(jī)制來完成對(duì)她的處理。

如何自定義異常嚷节?自定義異常首先要做的當(dāng)然是繼承 java.lang.Exception 類,不然你要自己重新寫一個(gè)嗎衩婚?然后提供一個(gè)空構(gòu)造函數(shù)和一個(gè)有參的構(gòu)造函數(shù)效斑,在其內(nèi)部調(diào)用 super 關(guān)鍵字給父類的私有屬性 detailMessage 屬性賦值。重寫 toString() 方法缓屠,輸出格式為:類名:detailMessage。根據(jù)具體需求還可以重寫printStackTrace()方法敌完。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滨溉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晦攒,更是在濱河造成了極大的恐慌,老刑警劉巖脯颜,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栋操,死亡現(xiàn)場離奇詭異,居然都是意外死亡讼庇,警方通過查閱死者的電腦和手機(jī)近尚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歼跟,“玉大人,你說我怎么就攤上這事哈街。” “怎么了骚秦?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵作箍,是天一觀的道長。 經(jīng)常有香客問我胞得,道長,這世上最難降的妖魔是什么跃巡? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任牧愁,我火速辦了婚禮,結(jié)果婚禮上猪半,老公的妹妹穿的比我還像新娘。我一直安慰自己办龄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布安接。 她就那樣靜靜地躺著英融,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驶悟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天硫豆,我揣著相機(jī)與錄音,去河邊找鬼旨别。 笑死,一個(gè)胖子當(dāng)著我的面吹牛秸弛,可吹牛的內(nèi)容都是我干的洪碳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼瞳腌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了憎兽?” 一聲冷哼從身側(cè)響起吵冒,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎痹栖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疗我,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡南捂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了麦牺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞭缭。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖岭辣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仑濒,我是刑警寧澤叹话,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布渣刷,位于F島的核電站鹦肿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞭吃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一歪架、第九天 我趴在偏房一處隱蔽的房頂上張望霹陡。 院中可真熱鬧,春花似錦烹棉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至摘昌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間聪黎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工杀赢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留湘纵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓梧喷,卻偏偏與公主長得像脖咐,于是被迫代替她去往敵國和親汇歹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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

  • 引言 在程序運(yùn)行過程中(注意是運(yùn)行階段派歌,程序可以通過編譯)痰哨,如果JVM檢測出一個(gè)不可能執(zhí)行的操作,就會(huì)出現(xiàn)運(yùn)行時(shí)錯(cuò)...
    Steven1997閱讀 2,431評(píng)論 1 6
  • packagetestexcrpltiom; importjava.text.ParseException; im...
    猿學(xué)閱讀 1,467評(píng)論 0 2
  • 這一日早抠,我們幾經(jīng)輾轉(zhuǎn)撬讽,來到貴州最有名的古鎮(zhèn)故鄉(xiāng)——鎮(zhèn)遠(yuǎn)蕊连。 鎮(zhèn)遠(yuǎn)是座歷史悠久的苗鄉(xiāng)古鎮(zhèn)游昼,苗族、侗族自治州...
    淡定姐姐閱讀 276評(píng)論 0 1
  • 現(xiàn)在的男女認(rèn)識(shí)真的 好簡單羊赵,陌陌?探探昧捷?附近的人罐寨?等等各種交友平臺(tái)靡挥,往往這樣的感情真的不會(huì)有人去珍惜吧畢竟來的太快...
    過呀過呀閱讀 274評(píng)論 0 0
  • 我知道這是今年最后一天和你在一起 你才哭的這么傷心 哭了一整天 整個(gè)江南因?yàn)槟阋叨伎蘖?秋天 我的情人 沒有人知...
    王秋煜閱讀 268評(píng)論 6 5