Exception vs Error
一個(gè)形象的比喻
假如你開車上山,車壞了,你拿出工具箱修一修,修好繼續(xù)上路(Exception被捕獲,從異常中恢復(fù),繼續(xù)程序的運(yùn)行),車壞了,你不知道怎么修,打電話告訴修車行,告訴你是什么問題,要車行過來修。(在當(dāng)前的邏輯背景下,你不知道是怎么樣的處理邏輯,把異常拋出去到更高的業(yè)務(wù)層來處理)。你打電話的時(shí)候,要盡量具體,不能只說我車動(dòng)不了了。那修車行很難定位你的問題。(要補(bǔ)貨特定的異常,不能捕獲類似Exception的通用異常)。還有一種情況是,你開車上山,山塌了,這你還能修嗎?(Error:導(dǎo)致你的運(yùn)行環(huán)境進(jìn)入不正常的狀態(tài),很難恢復(fù))
NoClassDefFoundError 與 ClassNotFoundException 區(qū)別
- NoClassDefFoundError -> Error 會(huì)導(dǎo)致程序處于非正常狀態(tài),不可捕獲
- ClassNotFoundException -> Exception 可捕獲,編譯期可檢查Exception,需要顯示的捕獲(補(bǔ)充:Exception 分為(在編譯期)可檢查和不可檢查的Exception,編譯期可檢查Exception,需要顯示的捕獲;編譯期不可檢查的Exception就是所謂的運(yùn)行時(shí)異常(RuntimeException: NullPointException),需要根據(jù)具體情況進(jìn)行捕獲處理)
throw、throws 關(guān)鍵字
- throw 拋出一個(gè)異常,寫在方法body體中,修飾一個(gè)異常實(shí)例
- throws 定義一個(gè)異常,類似try-catch-throw,寫在方法簽名/類名之后,修飾方法/類
try-catch-finally
異常捕獲需要注意
- 盡量不要捕獲類似Exception的通用異常,應(yīng)該捕獲特定異常
- 不要生吞異常,發(fā)生異常的時(shí)候,盡量提供更多異常cause信息并記錄到日志中,盡量不要輸出全部堆棧信息到console中,這樣做不僅影響程序性能而且在復(fù)雜系統(tǒng)中很難定位問題
自定異常需要注意
- 是否要定義成Checked Exception ( eg : IOException), 這種異常的設(shè)計(jì)初衷是為了從異常情況中恢復(fù),設(shè)計(jì)者應(yīng)該有足夠的信息對(duì)異常進(jìn)行分類
- 信息安全: 在保證診斷信息足夠的同時(shí),需要避免包含敏感信息,避免潛在的安全問題。(eg: java.net.ConnectException 的出錯(cuò)信息Connection refused (Connection refused)并不包含具體的機(jī)器名,IP,密碼等)
性能角度看Java異常處理機(jī)制
- try-catch代碼塊會(huì)影響JVM對(duì)代碼進(jìn)行優(yōu)化,所以會(huì)產(chǎn)生額外的性能開銷,建議僅捕獲有不要的代碼段,不要一個(gè)try包住整段代碼。此外,不要用try-catch來控制程序流程,因?yàn)樗h(yuǎn)比條件語句 (if-else /switch) 要低效
- Java 每實(shí)例化一個(gè)Exception都需要對(duì)當(dāng)前的棧進(jìn)行快照,這是一個(gè)比較重的操作,如果發(fā)生頻繁,這個(gè)開銷就不能被忽略了