Exception和Error有什么區(qū)別?

1.異常:這種情況下的異常电谣,可以通過(guò)完善任務(wù)重試機(jī)制秽梅,當(dāng)執(zhí)行異常時(shí)抹蚀,保存當(dāng)前任務(wù)信息加入重試隊(duì)列。重試的策略根據(jù)業(yè)務(wù)需要決定企垦,當(dāng)達(dá)到重試上限依然無(wú)法成功环壤,記錄任務(wù)執(zhí)行失敗,同時(shí)發(fā)出告警钞诡。

2.日志:類(lèi)比消息中間件郑现,處在不同線程之間的同一任務(wù),簡(jiǎn)單高效一點(diǎn)的做法可能是用traceId/requestId串聯(lián)荧降。有些日志系統(tǒng)本身支持MDC/NDC功能接箫,可以串聯(lián)相關(guān)聯(lián)的日志。

需深入學(xué)習(xí)理解

image.png
  • Throwable:它是異常處理機(jī)制的基本組成類(lèi)型朵诫,在 Java 中只有 Throwable 類(lèi)型的實(shí)例才可以被拋出(throw)或者捕獲(catch)辛友。
  • Exception 和 Error 都是繼承了 Throwable 類(lèi)。

Exception 和 Error 體現(xiàn)了 Java 平臺(tái)設(shè)設(shè)計(jì)者對(duì)不同異常情況的分類(lèi)剪返。

  • Error:系統(tǒng)錯(cuò)誤废累,虛擬機(jī)出錯(cuò),我們處理不了脱盲,也不需要我們來(lái)處理邑滨。比如OutOfMeoryError。
  • Exception:可以捕獲的異常钱反,且作出處理掖看。也就是要么捕獲異常并作出處理,要么繼續(xù)拋出異常诈铛。

Exception又分為檢查型異常和非檢查型異常

  • 檢查型異常:在源代碼里必須顯式地進(jìn)行捕獲處理乙各,這是編譯期檢查的一部分墨礁。如FileNotFoundException客戶(hù)端需要知道是文件沒(méi)有找到的問(wèn)題幢竹,客戶(hù)端可以通過(guò)其它方法來(lái)解決這個(gè)問(wèn)題如更換其它路徑等。
  • 非檢查型異常:就是所謂的運(yùn)行時(shí)異常恩静,類(lèi)似 NullPointerException焕毫,通常是可以編碼避免的邏輯錯(cuò)誤,具體根據(jù)需要來(lái)判斷是否需要捕獲驶乾,并不會(huì)在編譯期強(qiáng)制要求邑飒。

第一,理解 Throwable级乐、Exception疙咸、Error 的設(shè)計(jì)和分類(lèi)。

掌握那些應(yīng)用最為廣泛的子類(lèi)

比如 NoClassDefFoundError 和ClassNotFoundException 有什么區(qū)別风科,這也是個(gè)經(jīng)典的入門(mén)題目撒轮。

常見(jiàn)異常:

  • ActivityNotFoundException:該異常是當(dāng)調(diào)用了 startActivity() 之后乞旦,找不到匹配的 Activity 時(shí)拋出該異常。
  • BadTokenException:當(dāng)添加一個(gè)新的 window 時(shí)题山,如果 LayoutParams 不合法兰粉,就會(huì)拋出該異常。
  • ClassCastException:父類(lèi)可以通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換成具體某個(gè)子類(lèi)顶瞳,但如果強(qiáng)轉(zhuǎn)的兩個(gè)類(lèi)之間不存在繼承關(guān)系玖姑,那么就會(huì)拋出該異常。
  • ConcurrentModificationException:同時(shí)修改異常
  • IndexOutOfBoundsException:數(shù)組越界異常
  • NullPointerException:空指針異常
  • IOException:IO 異常慨菱,屬于檢查型異常焰络,必須通過(guò) try catch 代碼塊捕獲才能通過(guò)編譯階段。
  • OutOfMemoryError:內(nèi)存溢出錯(cuò)誤符喝,這類(lèi)問(wèn)題屬于 Error舔琅。
  • StackOverflowError:這類(lèi)錯(cuò)誤很?chē)?yán)重,表示程序陷入了死循環(huán)當(dāng)中洲劣。
  • NoClassDefFoundError:通常出現(xiàn)的場(chǎng)景是:編譯階段沒(méi)問(wèn)題备蚓,但程序運(yùn)行期間卻出現(xiàn)該問(wèn)題。原因一般是由于打包時(shí)囱稽,jar 出現(xiàn)問(wèn)題郊尝,部分類(lèi)沒(méi)有打包進(jìn)去,導(dǎo)致的問(wèn)題战惊。
  • ClassNotFoundException:這個(gè)異常流昏,同樣屬于相關(guān)類(lèi)找不到的問(wèn)題,但出現(xiàn)的場(chǎng)景通常是由于程序中使用了反射吞获,或者動(dòng)態(tài)加載之類(lèi)的方式况凉,使用了錯(cuò)誤的類(lèi)名,導(dǎo)致的問(wèn)題各拷。還有可能是由于混淆導(dǎo)致刁绒。
  • NumberFormatException:數(shù)字轉(zhuǎn)換格式異常。

第二烤黍,理解 Java 語(yǔ)言中操作 Throwable 的元素和實(shí)踐知市。

try-catch-finally:捕獲異常
try (BufferedReader br = new BufferedReader(…);
     BufferedWriter writer = new BufferedWriter(…)) {
// Try-with-resources
// do something
catch ( IOException | XEception e) {// Multiple catch
   // Handle it
} finally{
// do something
}

throw 是語(yǔ)句拋出一個(gè)異常。
public class ThrowTest {
    public static void main(String[] args) {
        try{
            throwChecked(3);
        }catch(Exception e) {
            System.out.println(e.getMessage());
        }
        throwRuntime(-3);
    }
    //該方法內(nèi)拋出一個(gè)Exception異常對(duì)象速蕊,必須捕獲或拋給調(diào)用者
    public static void throwChecked(int a) throws Exception {
        if(a < 0) {
            throw new Exception("a的值應(yīng)大于0嫂丙,不符合要求")
        }
    }
    //該方法內(nèi)拋出一個(gè)RuntimeException對(duì)象,可以不理會(huì)直接交給JVM處理
    public static void throwRuntime(int a) {
        if(a < 0) {
            throw new RuntimeException("a的值應(yīng)大于0规哲,不符合要求")
        }
    }
}

  • throw語(yǔ)句用在方法體內(nèi),表示拋出異常,由方法體內(nèi)的語(yǔ)句處理
  • throw是具體向外拋異常的動(dòng)作跟啤,所以它是拋出一個(gè)異常實(shí)例。
  • throw要么和try-catch-finally語(yǔ)句配套使用,要么與throws配套使用
  • 如果拋出的是RuntimeException則既可以顯示使用try…catch捕獲也可以不理會(huì)它
throws 是方法可能拋出異常的聲明隅肥。
  • 用在聲明方法時(shí)关顷,表示該方法可能要拋出異常
  • 給調(diào)用者處理或者交給JVM。JVM對(duì)異常的處理方式是:打印異常的跟蹤棧信息并終止程序運(yùn)行武福。
  • throws可以聲明多個(gè)異常议双,用逗號(hào)隔開(kāi);
  • 調(diào)用者必須做出處理(捕獲或繼續(xù)拋出)捉片。否則編譯是不會(huì)通過(guò)的平痰。

注意:
方法覆蓋的時(shí)候,如果子類(lèi)覆蓋了父類(lèi)的方法伍纫,子類(lèi)的方法不能聲明拋出比父類(lèi)更多的異常類(lèi)型宗雇。如果聲明的比父類(lèi)更多的異常類(lèi)型,編譯器是通不過(guò)的莹规。

遵循“Throw early catch late”原則

簡(jiǎn)單來(lái)說(shuō)就是:在異常出現(xiàn)時(shí)就將其拋出赔蒲,抓取應(yīng)該在能夠獲取足夠信息的時(shí)候。簡(jiǎn)單來(lái)說(shuō)良漱,底層的方法應(yīng)該更多的拋出異常舞虱,異常應(yīng)該更多的在頂層代碼中抓取處理。

第三母市,異常處理的兩大基本原則

  • 盡量不要捕獲類(lèi)似 Exception 這樣的通用異常矾兜,而是應(yīng)該捕獲特定異常。
  • 不要生吞(swallow)異常患久。
為什么要盡量捕獲特定異常椅寺?
  • 軟件工程是門(mén)協(xié)作的藝術(shù),所以我們有義務(wù)讓自己的代碼能夠直觀地體現(xiàn)出盡量多的信息蒋失。
  • Exception無(wú)法提供具體的異常信息返帕,不利于處理;強(qiáng)制客戶(hù)端處理(抓雀萃臁)一些不需要關(guān)注的異常荆萤。
什么是生吞異常?
  • 生吞異常嫉髓,往往是基于假設(shè)這段代碼可能不會(huì)發(fā)生观腊,或者感覺(jué)忽略異常是無(wú)所謂的,直接try catch掉算行,不做任何處理,不把異常拋出來(lái)苫耸,或者也沒(méi)有輸出到日志(Logger)之類(lèi)州邢。
  • 存在的隱患是:程序可能在后續(xù)代碼以不可控的方式結(jié)束。開(kāi)發(fā)人員就很難找到問(wèn)題所在,什么原因?qū)е碌漠惓量淌!?/li>

第四骗村,自定義異常

除了保證提供足夠的信息,還有兩點(diǎn)需要考慮:

  • 是否需要定義成 Checked Exception
  • 在保證診斷信息足夠的同時(shí)呀枢,也要考慮避免包含敏感信息胚股,因?yàn)槟菢涌赡軐?dǎo)致潛在的安全問(wèn)題。
public class AuctionException extends Exception {
    //無(wú)參構(gòu)造
    public AuctionException() {}
    //含參構(gòu)造
    //通過(guò)調(diào)用父類(lèi)的構(gòu)造器將字符串msg傳給異常對(duì)象的massage屬性裙秋,
    //massage屬性就是對(duì)異常的描述
    public AuctionException(String msg) {
        super(msg);
    }
}

第五琅拌,性能分析

  • try-catch 代碼段會(huì)產(chǎn)生額外的性能開(kāi)銷(xiāo)
  • Java 每實(shí)例化一個(gè) Exception,都會(huì)對(duì)當(dāng)時(shí)的棧進(jìn)行快照摘刑,這是一個(gè)相對(duì)比較重的操作进宝。

或者換個(gè)角度說(shuō),它往往會(huì)影響 JVM 對(duì)代碼進(jìn)行優(yōu)化枷恕。

建議

  • 不要過(guò)度使用異常:對(duì)于完全已知的錯(cuò)誤應(yīng)編寫(xiě)處理這種錯(cuò)誤代碼從而提高代碼的健壯性党晋,只有外部的、不能確定的和不可預(yù)知的運(yùn)行時(shí)錯(cuò)誤使是用異常徐块,并且異常機(jī)制的效率低于正常的流程控制未玻。

  • 僅捕獲有必要的代碼段,盡量不要一個(gè)大的 try包住整段的代碼胡控;與此同時(shí)深胳,利用異常控制代碼流程铜犬,也不是一個(gè)好主意舞终,遠(yuǎn)比我們通常意義上的條件語(yǔ)句(if/else、switch)要低效癣猾。

當(dāng)我們的服務(wù)出現(xiàn)反應(yīng)變慢敛劝、吞吐量下降的時(shí)候,檢查發(fā)生最頻繁的 Exception 也是一種思路纷宇。

心得感悟(摘抄評(píng)論區(qū))

1 不要推諉或延遲處理異常夸盟,就地解決最好,并且需要實(shí)實(shí)在在的進(jìn)行處理像捶,而不是只捕捉上陕,不動(dòng)作。

2 一個(gè)函數(shù)盡管拋出了多個(gè)異常拓春,但是只有一個(gè)異呈筒荆可被傳播到調(diào)用端。最后被拋出的異常時(shí)唯一被調(diào)用端接收的異常硼莽,其他異常都會(huì)被吞沒(méi)掩蓋庶溶。如果調(diào)用端要知道造成失敗的最初原因,程序之中就絕不能掩蓋任何異常。

3 不要在finally代碼塊中處理返回值偏螺。

4 按照我們程序員的慣性認(rèn)知:當(dāng)遇到return語(yǔ)句的時(shí)候行疏,執(zhí)行函數(shù)會(huì)立刻返回。但是套像,在Java語(yǔ)言中酿联,如果存在finally就會(huì)有例外。除了return語(yǔ)句夺巩,try代碼塊中的break或continue語(yǔ)句也可能使控制權(quán)進(jìn)入finally代碼塊贞让。

5 請(qǐng)勿在try代碼塊中調(diào)用return、break或continue語(yǔ)句劲够。萬(wàn)一無(wú)法避免震桶,一定要確保finally的存在不會(huì)改變函數(shù)的返回值。

6 函數(shù)返回值有兩種類(lèi)型:值類(lèi)型與對(duì)象引用征绎。對(duì)于對(duì)象引用蹲姐,要特別小心,如果在finally代碼塊中對(duì)函數(shù)返回的對(duì)象成員屬性進(jìn)行了修改人柿,即使不在finally塊中顯式調(diào)用return語(yǔ)句柴墩,這個(gè)修改也會(huì)作用于返回值上。

7 勿將異常用于控制流凫岖。

8 如無(wú)必要江咳,勿用異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哥放,一起剝皮案震驚了整個(gè)濱河市歼指,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌甥雕,老刑警劉巖踩身,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異社露,居然都是意外死亡挟阻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)峭弟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)附鸽,“玉大人,你說(shuō)我怎么就攤上這事瞒瘸】辣福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵挨务,是天一觀的道長(zhǎng)击你。 經(jīng)常有香客問(wèn)我玉组,道長(zhǎng)谎柄,這世上最難降的妖魔是什么丁侄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮朝巫,結(jié)果婚禮上鸿摇,老公的妹妹穿的比我還像新娘。我一直安慰自己劈猿,他們只是感情好拙吉,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著揪荣,像睡著了一般筷黔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仗颈,一...
    開(kāi)封第一講書(shū)人閱讀 52,337評(píng)論 1 310
  • 那天佛舱,我揣著相機(jī)與錄音,去河邊找鬼挨决。 笑死请祖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脖祈。 我是一名探鬼主播肆捕,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼盖高!你這毒婦竟也來(lái)了慎陵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喻奥,失蹤者是張志新(化名)和其女友劉穎席纽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體映凳,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胆筒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诈豌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仆救。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖矫渔,靈堂內(nèi)的尸體忽然破棺而出彤蔽,到底是詐尸還是另有隱情,我是刑警寧澤庙洼,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布顿痪,位于F島的核電站镊辕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蚁袭。R本人自食惡果不足惜征懈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揩悄。 院中可真熱鬧卖哎,春花似錦、人聲如沸删性。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹬挺。三九已至维贺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巴帮,已是汗流浹背溯泣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晰韵,地道東北人发乔。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雪猪,于是被迫代替她去往敵國(guó)和親栏尚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

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

  • 簡(jiǎn)述Java異常機(jī)制的優(yōu)點(diǎn) Java語(yǔ)言在設(shè)計(jì)之初就提供了相對(duì)完善的異常處理機(jī)制只恨,這也是Java的優(yōu)勢(shì)之一译仗;因?yàn)檫@...
    erki_stwee閱讀 345評(píng)論 0 0
  • 請(qǐng)對(duì)比Exception和Error,另外官觅,運(yùn)行時(shí)異常與一般異常有什么區(qū)別纵菌? Exception和Error Ex...
    L_live閱讀 248評(píng)論 0 0
  • 這一講的內(nèi)容主要涉及異常和錯(cuò)誤處理咱圆。這些年寫(xiě)了很多代碼,但在異常設(shè)計(jì)方面有欠缺功氨,一直感覺(jué)拿捏不準(zhǔn)序苏。何時(shí)定義異常,何...
    空谷幽心閱讀 644評(píng)論 0 50
  • 每個(gè)人都有很多的第一次捷凄, 第一次走路忱详,第一次開(kāi)車(chē),第一次主動(dòng)跟喜歡的人說(shuō)話(huà)跺涤,第一次做一頓好吃的給父母匈睁。 我的家鄉(xiāng)來(lái)...
    六點(diǎn)四十二閱讀 493評(píng)論 0 0
  • 初雪來(lái)的時(shí)候 我大概還在夢(mèng)里 緊緊的擁著暖 生怕被外面的冷瑟 掏空了溫度 南方的初雪 如期而至的時(shí)候 我也及時(shí)在家...
    云了蘇閱讀 265評(píng)論 9 2