1. 程式人生 > >Java 系列之Exception和Error

Java 系列之Exception和Error

Exception 和 Error

  1. Exception 和 Error 都是繼承了 Throwable 類,在 Java 中只有 Throwable 型別的例項才可以被丟擲(throw)或者捕獲(catch),它是異常處理機制的基本組成型別。
  2. Exception 和 Error 體現了 Java 平臺設計者對不同異常情況的分類。Exception 是程式正常執行中,可以預料的意外情況,可能並且應該被捕獲,進行相應處理。Error是程式發生了非正常,不可恢復的情況。無法捕獲,常見的有記憶體溢位OutOfMemoryError等,是Error的子類。
  3. Exception 又分為可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在原始碼裡必須顯式地進行捕獲處理,這是編譯期檢查的一部分。不可查的 Error,是 Throwable 不是 Exception。 不檢查異常就是所謂的執行時異常,類似 NullPointerException、ArrayIndexOutOfBoundsException 之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,並不會在編譯期強制要求。

在這裡插入圖片描述

異常捕獲

try {
  // 業務程式碼
  // …
  Thread.sleep(1000L);
} catch (Exception e) {
  // Ignore it
}
  1. 縮小異常捕獲範圍,不使用Exception這樣的通用異常,捕獲特定異常,Thread.sleep()丟擲的 InterruptedException
  2. 不要生吞(swallow)異常。這是異常處理中要特別注意的事情,因為很可能會導致非常難以診斷的詭異情況。 生吞異常,往往是基於假設這段程式碼可能不會發生,或者感覺忽略異常是無所謂的,但是千萬不要在產品程式碼做這種假設! 如果我們不把異常丟擲來,或者也沒有輸出到日誌(Logger)之類,程式可能在後續程式碼以不可控的方式結束。沒人能夠輕易判斷究竟是哪裡丟擲了異常,以及是什麼原因產生了異常。

效能方面

  • try-catch 程式碼段會產生額外的效能開銷,或者換個角度說,它往往會影響 JVM 對程式碼進行優化,所以建議僅捕獲有必要的程式碼段,儘量不要一個大的 try 包住整段的程式碼;與此同時,利用異常控制程式碼流程,也不是一個好主意,遠比我們通常意義上的條件語句(if/else、switch)要低效。

  • Java 每例項化一個 Exception,都會對當時的棧進行快照,這是一個相對比較重的操作。如果發生的非常頻繁,這個開銷可就不能被忽略了。

當我們的服務出現反應變慢、吞吐量下降的時候,檢查發生最頻繁的 Exception 也是一種思路。

老生常談