Java 系列之Exception和Error
阿新 • • 發佈:2018-12-20
Exception 和 Error
- Exception 和 Error 都是繼承了 Throwable 類,在 Java 中只有 Throwable 型別的例項才可以被丟擲(throw)或者捕獲(catch),它是異常處理機制的基本組成型別。
- Exception 和 Error 體現了 Java 平臺設計者對不同異常情況的分類。Exception 是程式正常執行中,可以預料的意外情況,可能並且應該被捕獲,進行相應處理。Error是程式發生了非正常,不可恢復的情況。無法捕獲,常見的有記憶體溢位OutOfMemoryError等,是Error的子類。
- Exception 又分為可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在原始碼裡必須顯式地進行捕獲處理,這是編譯期檢查的一部分。不可查的 Error,是 Throwable 不是 Exception。 不檢查異常就是所謂的執行時異常,類似 NullPointerException、ArrayIndexOutOfBoundsException 之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,並不會在編譯期強制要求。
異常捕獲
try {
// 業務程式碼
// …
Thread.sleep(1000L);
} catch (Exception e) {
// Ignore it
}
- 縮小異常捕獲範圍,不使用
Exception
這樣的通用異常,捕獲特定異常,Thread.sleep()
丟擲的InterruptedException
。 - 不要生吞(swallow)異常。這是異常處理中要特別注意的事情,因為很可能會導致非常難以診斷的詭異情況。 生吞異常,往往是基於假設這段程式碼可能不會發生,或者感覺忽略異常是無所謂的,但是千萬不要在產品程式碼做這種假設! 如果我們不把異常丟擲來,或者也沒有輸出到日誌(Logger)之類,程式可能在後續程式碼以不可控的方式結束。沒人能夠輕易判斷究竟是哪裡丟擲了異常,以及是什麼原因產生了異常。
效能方面
-
try-catch 程式碼段會產生額外的效能開銷,或者換個角度說,它往往會影響 JVM 對程式碼進行優化,所以建議僅捕獲有必要的程式碼段,儘量不要一個大的 try 包住整段的程式碼;與此同時,利用異常控制程式碼流程,也不是一個好主意,遠比我們通常意義上的條件語句(if/else、switch)要低效。
-
Java 每例項化一個 Exception,都會對當時的棧進行快照,這是一個相對比較重的操作。如果發生的非常頻繁,這個開銷可就不能被忽略了。
當我們的服務出現反應變慢、吞吐量下降的時候,檢查發生最頻繁的 Exception 也是一種思路。