第十章 異常處理

異常概述

  • 依賴于try catch finally throw throws五個關鍵字
  • Java把一場分為兩種:Checked Runtime滥酥,Checked異嘲枚桑可以在編譯階段被發(fā)現蝗肪,所以強制程序處理所有的Checked異常斜友,Runtime異常無需處理
  • 無法窮舉所有的異常情況词顾,錯誤處理代碼和業(yè)務實現代碼混雜八秃,影響可讀性,增加維護難度计技,使用Java異常處理機制就可以解決這個問題
  • Java把錯誤分為Exception和Error喜德,Error一般指與虛擬機相關的問題,通常程序無法處理這些錯誤垮媒,所以不應該使用catch捕捉Error對象

異常處理機制

使用try...catch捕獲異常

try
{
//業(yè)務實現代碼
}
catch (Excption e)
{
//處理異常
}
  • 當try中業(yè)務邏輯代碼出現異常時舍悯,系統(tǒng)會自動生成一個異常對象交給Java運行時環(huán)境航棱,拋出(throw)異常

  • 拋出異常后,Java運行時環(huán)境收到異常對象時尋找對應的catch塊交給其處理萌衬,如果找不到捕獲異常的catch塊饮醇,則運行時環(huán)境種植,程序退出

  • 會依次判斷該異常對象是否為catch塊后異常類或其子類的實例秕豫,如果是則交由其處理

  • try塊后的花括號不能省略朴艰,catch也不能省略

  • catch應該先處理小異常再處理大異常,把父類異常的catch塊排在子類的后面混移,否則會出現編譯錯誤

  • Java7提供多異常捕獲祠墅,一個catch可以捕獲多種類型的異常,用|隔開歌径,捕獲多種類型的異常時毁嗦,異常變量有隱式的final修飾,程序不能對其重新賦值catch (...|...|... e){}

  • 異常對象包含的訪問信息的方法:getMessage printStackTrace getStackTrance

finally回收資源

  • try塊內打開的物理資源(數據庫連接回铛、網絡連接狗准、磁盤文件等),這些物理資源必須顯式回收
try{}
catch(.. e){}
catch(.. e){}
...
finally
{
//回收資源
}
  • 只有try塊時必須的茵肃,catch和finally至少出現其中之一腔长,finally位于catch之后,catch位于try之后
  • 除非再try或catch中調用了退出虛擬機的方法System.exit(1);验残,不管怎么樣finally塊總會被執(zhí)行
  • 通常不要在finally塊中使用return或throw方法終止語句捞附,會導致try catch中的return throw語句失效
  • 層次太深的潛逃異常處理沒有太大的必要,會導致程序可讀性降低
  • Java7自動給關閉資源的try語句胚膊,資源的實現類必須實現AutoCloseable或Closeable(AutoCloseable子接口故俐,只能拋出IOException或其子類)接口,也就是實現了close()方法try(//聲明初始可關閉的資源){}
  • 自動關閉資源的try語句相當于包含了隱式的finally塊紊婉,所以這個try可以既沒有catch塊也沒有finally塊

Checked和Runtime異常體系

  • 不是RuntimeException類及其子類的異常實例稱為Checked異常
  • 對于Checked異常的處理方式
    • 當明確知道如何處理時使用try...catch捕獲修復該異常
    • 當前方法不知道如何處理時應該在定義該方法時拋出該異常
  • Runtime異常無需顯式聲明拋出药版,如果需要捕獲,也可以使用try...catch
  • throws聲明拋出異常喻犁,throws EC1,EC2...
    public static void main(String[] args) throws IOException {}
  • 當前方法不知如何處理該異常槽片,則拋出有上一級調用者處理,如果main方法也不知道肢础,也可以使用throws拋出交給JVM處理还栓。
  • JVM處理異常:打印異常跟蹤棧信息,終止程序運行传轰。
  • 重寫使用throws聲明拋出異常的方法時剩盒,子類方法聲明拋出的異常類型應該時父類的相同類或子類,并且子類方法聲明拋出的異常不能比父類聲明的多

throw拋出異常

  • Java允許自行拋出異常慨蛙,使用throw語句throw ExceptionInstance;
  • 如果拋出Checked異常辽聊,需要處于try塊或有throws聲明拋出的方法中纪挎,如果是Runtime異常,則不需要跟匆,自行拋出Runtime異常比Checked異常靈活

自定義異常類

  • 需要繼承Exception基類异袄,如果自定義Runtime異常則可以繼承RuntimeException基類
  • 通常需要兩個構造器,一個無參玛臂,一個字符串參數(描述異常對象的信息)烤蜕,getMessage()返回值public myException(String msg){super(msg);}

catch和throw同時使用

  • 在出現異常的方法內捕獲并處理異常,該方法的調用者將不能再次捕獲該異常
  • 方法簽名中聲明拋出該異常迹冤,改異常將完全交給方法的調用者處理
  • 在實際應用中讽营,完全處理一個異常必須由幾方法寫作才可以,比如在出現異常的方法中捕獲并處理部分叁巨,還需要再次拋出斑匪,讓調用者也捕獲到異常處理剩下的部分
  • 在catch塊中結合throw語句完成
catch (Exception e)
{
    e.printStackTrace();//在本方法中只是進行一個打印異常信息的操作
    throw new AuctionException("想傳遞的信息");//再次拋出自定義異常
}
  • 企業(yè)級應用對異常處理通常分為兩部分
    • 應用后臺需要通過日志記錄異常發(fā)生的詳細情況
    • 向應用的使用者傳達提示
  • Java7增強的throw語句,編譯器會檢查throw語句拋出異常的實際類型锋勺,而不是僅根據catch后的類型判斷,因此方法聲明中只需要聲明拋出實際類型的異常即可

異常鏈

  • 不應該把底層的異常傳到用戶界面狡蝶,對于用戶庶橱,此舉沒有任何幫助,且對于惡意用戶贪惹,暴露異常是不安全的
  • 應該把底層原始異常捕獲苏章,拋出一個新的業(yè)務異常,這種處理方式叫做異常轉譯奏瞬,完全符合面向對象的封裝原則
  • 捕獲一個異常接著拋出另一個異常枫绅,并把原始已異常信息保存下來是一種典型的鏈式處理,職責鏈模式硼端,也稱為異常鏈
  • Java1.4后Throwable的子類在構造器中可以接受一個cause對象作為參數并淋,表示原始異常,這樣可以通過異常鏈追蹤到異常最初發(fā)生的位置珍昨,獲取原始異常信息

異常跟蹤棧

  • 只要異常沒有被完全捕獲县耽,從發(fā)生異常的方法逐漸向外傳播,打印異常的跟蹤棧信息
  • printStackTrace()方法用于調試镣典,最終還是應該避免使用它兔毙,應該對捕獲的異常進行處理,而不是簡單的打印

異常處理規(guī)則

  • 成功處理異常的四個目標
    • 是程序代碼混亂最小化
    • 捕獲并保留診斷信息
    • 通知合適的人員
    • 采用合適的方式結束異承执海活動
  • 異常只應該用于處理非正常的情況澎剥,不要去代替正常的流程控制
  • 不要使用過于龐大的try塊,應該分割成單獨的try塊赶舆,分別捕獲并處理異常
  • 避免使用Catch All語句哑姚,catch(Throwable t){...}
  • 不要忽略捕獲到的異常趾唱,去處理異常,重新拋出新異常蜻懦,再在合適的層處理異常
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末甜癞,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子宛乃,更是在濱河造成了極大的恐慌悠咱,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件征炼,死亡現場離奇詭異析既,居然都是意外死亡,警方通過查閱死者的電腦和手機谆奥,發(fā)現死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門眼坏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酸些,你說我怎么就攤上這事宰译。” “怎么了魄懂?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵沿侈,是天一觀的道長。 經常有香客問我市栗,道長缀拭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任填帽,我火速辦了婚禮蛛淋,結果婚禮上,老公的妹妹穿的比我還像新娘篡腌。我一直安慰自己褐荷,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布哀蘑。 她就那樣靜靜地躺著诚卸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绘迁。 梳的紋絲不亂的頭發(fā)上合溺,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音缀台,去河邊找鬼棠赛。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的睛约。 我是一名探鬼主播鼎俘,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辩涝!你這毒婦竟也來了贸伐?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤怔揩,失蹤者是張志新(化名)和其女友劉穎捉邢,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體商膊,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡伏伐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了晕拆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藐翎。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖实幕,靈堂內的尸體忽然破棺而出吝镣,到底是詐尸還是另有隱情,我是刑警寧澤茬缩,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布赤惊,位于F島的核電站,受9級特大地震影響凰锡,放射性物質發(fā)生泄漏。R本人自食惡果不足惜圈暗,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一掂为、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧员串,春花似錦勇哗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至渺鹦,卻和暖如春扰法,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背毅厚。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工塞颁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓祠锣,卻偏偏與公主長得像酷窥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子伴网,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容

  • 引言 在程序運行過程中(注意是運行階段蓬推,程序可以通過編譯),如果JVM檢測出一個不可能執(zhí)行的操作澡腾,就會出現運行時錯...
    Steven1997閱讀 2,411評論 1 6
  • 八沸伏、深入理解java異常處理機制 引子try…catch…finally恐怕是大家再熟悉不過的語句了, 你的答案是...
    壹點零閱讀 1,535評論 0 0
  • A+B問題 描述 給出兩個整數a和b, 求他們的和, 但不能使用 + 等數學運算符蛋铆。 思路: 1馋评、 采用二進制進...
    奇跡迪閱讀 367評論 0 2
  • 2017年8月31日留特,8月的最后一天,輾轉縣城里的大小酒店玛瘸,想著原來那個日子還有場地的酒店把宴會定下來蜕青,結果沒有了...
    藍天里的云朵閱讀 257評論 0 0
  • 看了78%了,很多觀點糊渊,解釋這個世界的方式都給人一種很新奇的感覺右核,看到豆瓣上的評論褒貶不一,但對我來說還是很有幫助...
    output閱讀 243評論 0 0