Java異常處理12條軍規

摘要: 簡單實用的建議。java

Fundebug經受權轉載,版權歸原做者全部。數據庫

在Java語言中,異常從使用方式上能夠分爲兩大類:網絡

  • CheckedException
  • UncheckedException

在Java中類的異常結構圖以下:性能

  • 可檢查異常須要在方法上聲明,通常要求調用者必須感知異常可能發生,而且對可能發生的異常進行處理。能夠理解成系統正常狀態下極可能發生的狀況,一般發生在經過網絡調用外部系統或者使用文件系統時,在這種狀況下,錯誤是可能恢復的,調用者能夠根據異常作出必要的處理,例如重試或者資源清理等。spa

  • 非檢查異常是不須要在throws子句中聲明的異常。JVM根本不會強制您處理它們,由於它們主要是因爲程序錯誤而在運行時生成的。它們擴展了RuntimeException。最多見的例子是NullPointerException 可能不該該重試未經檢查的異常,而且正確的操做一般應該是什麼都不作,並讓它從您的方法和執行堆棧中出來。在高執行級別,應記錄此類異常。debug

  • Error是最爲嚴重的運行時錯誤,幾乎是不可能恢復和處理,一些示例是OutOfMemoryError,LinkageError和StackOverflowError。它們一般會使程序或程序的一部分崩潰。只有良好的日誌記錄練習才能幫助您肯定錯誤的確切緣由.設計

在異常處理時的幾點建議:日誌

1. 永遠不要catch中吞掉異常,不然在系統發生錯誤時,你永遠不知道到底發生了什麼

catch (SomeException e) {  
    return  null;
}
複製代碼

2. 儘可能使用特定的異常而不是一概使用Exception這樣太泛泛的異常

public void foo() throws Exception { //錯誤的作法}
複製代碼
public void foo() throws MyBusinessException1, MyBusinessException2 { //正確的作法}
複製代碼

一味的使用Exception,這樣就違背了可檢查異常的設計初衷,由於調用都不知道Exception究竟是什麼,也不知道該如何處理。捕獲異常時,也不要捕獲範圍太大,例如捕獲Exception,相反,只捕獲你能處理的異常,應該處理的異常。即然方法的聲明者在方法上聲明瞭不一樣類型的可檢查異常,他是但願調用者區別對待不一樣異常的。code

3. Never catch Throwable class

​永遠不要捕獲Throwable,由於Error也是繼承自它,Error是Jvm都處理不了的錯誤,你能處理?因此基於有些Jvm在Error時就不會讓你catch住。orm

4. 正確的封裝和傳遞異常**

不要丟失異常棧,由於異常棧對於定位原始錯誤很關鍵

catch (SomeException e) {throw  new MyServiceException("Some information: " + e.getMessage());  //錯誤的作法}
複製代碼

必定要保留原始的異常:

catch (SomeException e) {   throw new MyServiceException("Some information: " , e);  //正確的打開方式}
複製代碼

5. 要打印異常,就不要拋出,不要二者都作

catch (SomeException e) {   
    LOGGER.error("Some information", e);
    throw e;
}
複製代碼

這樣的log沒有任何意義,只會打印出一連串的error log,對於定位問題無濟於事。

6. 不要在finally塊中拋出異常

若是在finally中拋出異常,將會覆蓋原始的異常,若是finally中真的可能會發生異常,那必定要處理並記錄它,不要向上拋。

7. 不要使用printStackTrace

要給異常添加上有用的上下文信息,單純的異常棧,沒有太大意義

8. Throw early catch late

異常界著名的原則,錯誤發生時及早拋出,而後在得到因此所有信息時再捕獲處理.也能夠理解爲在低層次拋出的異常,在足夠高的抽象層面才能更好的理解異常,而後捕獲處理。

9. 對於使用一些重量級資源的操做,發生異常時,必定記得清理

如網絡鏈接,數據庫操做等,能夠用try finally來作clean up的工做。

10. 不要使用異常來控制程序邏輯流程

咱們老是不經意間這麼作了,這樣使得代碼變動醜陋,使得正常業務邏輯和錯誤處理混淆不清;並且也可能會帶來性能問題,由於異常是個比較重的操做。

11. 及早校驗用戶的輸入

在最邊緣的入口校驗用戶的輸入,這樣使得咱們不用再更底層邏輯中到處校驗參數的合法性,能大大簡化業務邏輯中沒必要要的異常處理邏輯;相反,在業務中不若是擔憂參數的合法性,則應該使用衛語句拋出運行時異常,一步步把對參數錯誤的處理推到系統的邊緣,保持系統內部的清潔。

12. 在打印錯誤的log中儘可能在一行中包含儘量多的上下文

LOGGER.debug("enter A");LOGGER.debug("enter B"); //錯誤的方式
複製代碼
LOGGER.debug("enter A, enter B");//正確的方式
複製代碼
相關文章
相關標籤/搜索