
所有程序都會有錯誤發(fā)生,我們叫它bug
異常情形如影隨性的糾纏著,只有處理好這些異常情況才能保證服務(wù)正常期望運行,因此Java語言設(shè)計之初引入異常處理機制來規(guī)避異常于萌芽之中;
思考:
Exception與Error之間的區(qū)別是什么?
運行時異常與一般異常有什么區(qū)別?異常情況分類:Exception和Error
Exception:程序正常運行中,可以預(yù)料的意外情況,可能并且應(yīng)該被捕獲,進行相應(yīng)處理。
Error:在正常情況下不可能出現(xiàn)的情況,絕大部分的Error都會導(dǎo)致程序(如:JVM)處理非正常狀態(tài)、不可恢復(fù)狀態(tài)。既然是非正常情況,所以不便于也不需要捕獲,常見的比如OutOfMemoryError之類的都是Error的子類。Exception又分為可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在源代碼里必須顯式地進行捕獲處理,這是編譯期檢查的一部分。
注意:這里不可查的Error是Throwable不是Exception
不檢查異常就是運行時異常,類似NullPointerException、ArrayIndexOutOfBoundsException之類,具體根據(jù)需要來判斷是否需要捕獲,并不會再編譯期強制要求。
理解Throwable、Exception、Error的設(shè)計和分類
由于代碼堆棧不再是同步調(diào)用那種垂直的結(jié)構(gòu),我們往往看到的是特定的executor的堆棧,而不是業(yè)務(wù)方法調(diào)用關(guān)系,這種時候,我們怎么回溯問題呢?
答案:業(yè)務(wù)功能模塊分配ID,在記錄日志是將前后模塊的ID進行調(diào)用關(guān)系的串聯(lián),一并跟任務(wù)信息,進行日志保存
Exception和Error都是繼承Throwable類,而且在Java中只有Throwable類型的實例才可以被拋出(throw)或者捕獲(catch),它是異常處理機制的基本組成類型。
Error、Exception或者RuntimeException有哪些?

NoClassDefFoundError和ClassNotFoundException有什么區(qū)別?
理解Java語言中操作Throwable的元素和實踐
盡量不要捕獲直接Exception這樣的通用異常,而是應(yīng)該捕獲特定異常;需要了解可能會拋出的特定異常如IterruptedException
不要生吞異常,往往是基于假設(shè)這段代碼不會發(fā)生,或者感覺忽略異常無所謂的,但是千萬不要在產(chǎn)品代碼中做這種假設(shè)
Throw early,catch late原則
- 自定義異常需要注意的點
是否需要定義成可檢查的Exception(checked Exception),因為這種類型設(shè)計的初衷更是為了從宜昌情況恢復(fù),作為異常設(shè)計者,我們往往有充足的信息進行異常分類
-
為保證診斷信息足夠的同時,也要考慮避免包含敏感信息,因為那樣可能導(dǎo)致潛在的安全問題。
如果我們看Java的標準類庫,你可能注意到類似Java.net.ConnectionException,出錯信息是類似“Connection refused”,而不包含具體的機器名、IP、端口等,一個重要考量就是信息安全。類似的情況在日志中也有,比如,用戶數(shù)據(jù)一般是不可以輸出到日志里面的。
總結(jié)Summary
- 當(dāng)我們的服務(wù)出現(xiàn)反應(yīng)變慢、吞吐量下降的時候,檢查發(fā)生最頻繁的Exception也是一種思路
- 假如你開車上山,車壞了,你拿出工具箱修一修,修好繼續(xù)上路(Exception被捕獲,從異常中恢復(fù),繼續(xù)程序的運行)
- 車壞了,你不知道怎么修,打電話告訴修車行,告訴你是什么問題,要車行過來修。(在當(dāng)前的邏輯背景下,你不知道是怎么樣的處理邏輯,把異常拋出去到更高的業(yè)務(wù)層來處理)
- 你打電話的時候,要盡量具體,不能只說我車動不了了。那修車行很難定位你的問題。(要補貨特定的異常,不能捕獲類似Exception的通用異常)
- 還有一種情況是,你開車上山,山塌了,這你還能修嗎?(Error:導(dǎo)致你的運行環(huán)境進入不正常的狀態(tài),很難恢復(fù))