JavaSE 基礎(chǔ)學(xué)習(xí)之四 —— 異常的處理

接上篇《JavaSE 基礎(chǔ)學(xué)習(xí)之三 —— Java 的繼承與接口》


四. Java 核心專題 —— 異常處理

1. 兩種類型的異常

  • 運行時異常 (RuntimeException):不處理也能通過編譯顿痪,jvm 會幫助處理,也可以自行處理果复;
  • 其他異常:對于其他異常屡萤,如果不處理程序就不能通過編譯抵赢,必須自己處理薇溃;

注:
所有的異常產(chǎn)生之后厌均,都是一個類的實例對象刨裆,而且這些異常全部繼承于 Exception维贺;java 中對所有的異常都進行了細(xì)致分類它掂,每種異常都有一個具體的類。

2. 異常處理的關(guān)鍵字

(1) try... catch...

  • try 后面可以有多個 catch溯泣;
  • 所有的異常都是 Exception 的子類虐秋;
  • 多個 catch 的時候,父類的異常一定要寫在子類的后面垃沦;
  • Exception 可以認(rèn)為是萬能異常客给;
  • 常用 Exception 的方法:
    • getMessage(): 返回此 throwable 的詳細(xì)消息字符串;
    • toString():返回此 throwable 的簡短描述肢簿。
    • printStackTrace():打印異常的堆棧靶剑,將此 throwable 及其追蹤輸出至標(biāo)準(zhǔn)錯誤流;

(2) finally

finally 關(guān)鍵字后無論有沒有異常池充,最終都要執(zhí)行的操作桩引;

例:

public class Demo1 {
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            System.out.println(a/b);
        } catch (ArrayIndexOutOfBoundsException e) {
            // TODO: handle exception
            System.out.println("數(shù)組下標(biāo)越界");
        } catch (ArithmeticException e) {
            System.out.println("除數(shù)不能為 0");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e);
            System.out.println("其他異常");
        } finally {
            System.out.println("無論有沒有異常,最終都要執(zhí)行的操作");
        }
    }
}

(3) throw

throw 關(guān)鍵字表示在某種情況下纵菌,我們自己手動拋出的異常實例阐污;

:定義一個 Person 類,對其年齡進行設(shè)置咱圆,如果年齡超過 120笛辟,則認(rèn)為出現(xiàn)錯誤,手動拋出異常序苏。

public class Person {
    private int age = 10;
    public int getAge() {
        return age;
    }

    public void setAge(int age) throws Exception{
        try {
            if(age < 0 || age > 120) {
                throw new Exception("年齡有誤");
            } else {
                this.age = age;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如果運行了程序 setAge(130)手幢,則會拋出“年齡有誤”的異常。

(4) throws

throws 關(guān)鍵字在一個方法的方法簽名后面使用忱详,用處在于通過編譯围来,告訴使用者一旦調(diào)用了當(dāng)前方法,可能出現(xiàn)處理哪些異常匈睁,這樣可以令使用者盡量的回避異常监透;當(dāng)你的方法里拋出了 checked 異常,如你不 catch航唆,代表你當(dāng)時不處理(不想處理或沒條件處理)胀蛮,但你必須得通過"throws那個異常"告訴系統(tǒng)說,這兒有個問題糯钙,我現(xiàn)在不處理粪狼,將來一定別人要處理退腥,否則執(zhí)行到它,系統(tǒng)會"不優(yōu)雅"的崩潰再榄。
舉個例子狡刘,工兵張三發(fā)現(xiàn)了地雷,假如他處理完就完事兒了困鸥。但是他發(fā)現(xiàn)了地雷嗅蔬,自己卻沒帶齊工具,沒法處理窝革,他必須做個標(biāo)記购城,說這兒有一個地雷,別的工兵將來一定要處理虐译,否則將來有人踩上去會爆炸。
注意:throws只是標(biāo)記吴趴,并沒處理漆诽,程序執(zhí)行到那里,系統(tǒng)還是會崩潰锣枝!

public class Person1 {
    private int age;
    // throws 異常厢拭,通知此處代碼有問題
    public void setAge(int age) throws Exception{
        if(age < 0 || age > 120)
            throw new Exception("年齡有誤!");
        this.age = age;
        
    }
    public int getAge() {
        return age;
    }
}

3. 自定義異常

項目中撇叁,我們可以通過創(chuàng)建一個類繼承 jdk 提供的異常類 (RunTimeException 或 Exception)供鸠,自定義的實現(xiàn)一個異常類。

自定義異常的創(chuàng)建有利有弊:優(yōu)點如下:

  • 工作過程中陨闹,項目是分模塊或者分功能開發(fā)的楞捂,基本不會你一個人開發(fā)一整個項目,使用自定義異常類就統(tǒng)一了對外異常展示的方式趋厉;
  • 有時候我們遇到某些校驗或者問題時寨闹,需要直接結(jié)束掉當(dāng)前的請求,這時便可以通過拋出自定義異常來結(jié)束君账。例如繁堡,如果你項目中使用了SpringMVC比較新的版本的話有控制器增強,可以通過@ControllerAdvice注解寫一個控制器增強類來攔截自定義的異常并響應(yīng)給前端相應(yīng)的信息乡数;
  • 系統(tǒng)中有些錯誤是符合Java語法的椭蹄,但不符合我們項目的業(yè)務(wù)邏輯砰粹,使用自定義異掣馄可以在我們項目中某些特殊的業(yè)務(wù)邏輯時拋出異常。例如對于性別形庭,"中性".equals(sex)劫侧,性別等于中性時我們要拋出異常埋酬,而Java是不會有這種異常的哨啃;
  • 使用自定義異常繼承相關(guān)的異常來拋出處理后的異常信息可以隱藏底層的異常,這樣更安全写妥,異常信息也更加直觀拳球。自定義異常可以拋出我們自己想要拋出的信息珍特,可以通過拋出的信息區(qū)分異常發(fā)生的位置祝峻,根據(jù)異常名我們就可以知道哪里有異常,根據(jù)異常提示信息進行程序修改扎筒。例如莱找,空指針異常NullPointException,我們可以拋出信息為“xxx為空”定位異常位置嗜桌,而不用輸出堆棧信息奥溺。

自定義異常的缺點主要在于,發(fā)現(xiàn)異常骨宠、拋出異常以及處理異常的工作必須靠編程人員在代碼中利用異常處理機制自己完成浮定。這樣就相應(yīng)的增加了一些開發(fā)成本和工作量,所以項目沒必要的話层亿,也不一定非得要用上自定義異常桦卒,要能夠自己去權(quán)衡。

關(guān)于自定義異常匿又,可以參考《Java異常之自定義異撤皆郑》的博客。

4. 關(guān)于異常的編程建議

建議:

  1. 自己拋出的異常必須要填寫詳細(xì)的描述信息碌更,便于問題定位裕偿;
    • 例如:throw new IOException("Writing data error! Data: " + data.toString());
  2. 在程序中,選擇使用異常處理還是錯誤返回碼處理针贬,應(yīng)該根據(jù)是否有利于程序結(jié)構(gòu)來確定击费,且不能將異常和錯誤碼混合使用。通常情況下推薦異常處理桦他;
  3. 記錄異常時蔫巩,不要只保存 exception.getMessage(),一般可以通過日志工具記錄完整的異常堆棧信息快压;
  4. 一個方法不應(yīng)該拋出太多類型的異常圆仔。如果確實有很多異常類型,首先應(yīng)該考慮用異常來進行區(qū)別蔫劣。通常來說 throws / exception 子句標(biāo)明的異常最多不要超過三個坪郭;
  5. 異常捕獲盡量不要直接捕獲 catch(Exception ex),應(yīng)該把異常細(xì)分處理脉幢,設(shè)計更加合理的異常處理分支歪沃;
  6. public 類型的底層方法需要對輸入?yún)?shù)進行判斷嗦锐,如果參數(shù)不合法,應(yīng)該主動拋出 RuntimeException沪曙;

強烈建議

  1. 在調(diào)用的最高層奕污,必須處理所有的異常;
  2. 如果捕獲了異常液走,然后拋出新的異常碳默,則必須將原異常的信息全部包含在新的異常中;
  3. 系統(tǒng)非正常運行產(chǎn)生的異常捕獲之后缘眶,如果不對該異常進行處理嘱根,必須記錄日志;
  4. 對于多個異常的額情況巷懈,必須對應(yīng)多個 catch 分別處理该抒,禁止使用一個 catch 處理多個異常。如下例所示:
public void sample() {
    try {
        // 某個拋出異常塊
    }
    // 處理異常種類 1
    catch (IllegalStateException illEx) {
        log.wirte(illEx.printStackTrace());
        throw illex;
    }
    // 處理異常種類 2
    catch (SQLException SQLEx) {
        log.write(SQLEx.printStackTrace());
        throw SQLEx;
    }
    finally {
        // 釋放資源
    }
}

接下篇《JavaSE 基礎(chǔ)學(xué)習(xí)之五 —— IO 操作》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砸喻,一起剝皮案震驚了整個濱河市柔逼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌割岛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犯助,死亡現(xiàn)場離奇詭異癣漆,居然都是意外死亡,警方通過查閱死者的電腦和手機剂买,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門惠爽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞬哼,你說我怎么就攤上這事婚肆。” “怎么了坐慰?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵较性,是天一觀的道長。 經(jīng)常有香客問我结胀,道長赞咙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任糟港,我火速辦了婚禮攀操,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秸抚。我一直安慰自己速和,他們只是感情好歹垫,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著颠放,像睡著了一般排惨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上慈迈,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天若贮,我揣著相機與錄音,去河邊找鬼痒留。 笑死谴麦,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伸头。 我是一名探鬼主播匾效,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼恤磷!你這毒婦竟也來了面哼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤扫步,失蹤者是張志新(化名)和其女友劉穎魔策,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體河胎,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡闯袒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了游岳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片政敢。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胚迫,靈堂內(nèi)的尸體忽然破棺而出喷户,到底是詐尸還是另有隱情,我是刑警寧澤访锻,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布褪尝,位于F島的核電站,受9級特大地震影響朗若,放射性物質(zhì)發(fā)生泄漏恼五。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一哭懈、第九天 我趴在偏房一處隱蔽的房頂上張望灾馒。 院中可真熱鬧,春花似錦遣总、人聲如沸睬罗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽容达。三九已至古涧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間花盐,已是汗流浹背羡滑。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留算芯,地道東北人柒昏。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像熙揍,于是被迫代替她去往敵國和親职祷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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