-
儘量不要 catch RuntimeException,比如 NullPointerException、IndexOutOfBoundsException 等等,應該用預檢查的方式來規避。
-
儘量使用 try-with-resource 來關閉資源:禁止在 try 塊中直接關閉資源,因為一旦
close()
之前發生了異常,那麼資源就無法關閉 -
不要捕獲 Throwable:很可能把超出程式處理能力之外的錯誤也捕獲了
-
不要省略異常資訊的記錄
-
不要記錄了異常又丟擲了異常
-
不要在 finally 塊中使用 return:try 塊中的 return 語句執行成功後,並不會馬上返回,而是繼續執行 finally 塊中的語句,如果 finally 塊中也存在 return 語句,那麼 try 塊中的 return 就將被覆蓋。
private int x = 0;
public int checkReturn() {
try {
return ++x;
} finally {
// try 塊中 x 返回的值為 1,到了 finally 塊中就返回 2 了
return ++x;
}
}
-
丟擲具體定義的檢查性異常而不是 Exception
-
捕獲具體的子類而不是捕獲 Exception 類
-
自定義異常時不要丟失堆疊跟蹤
-
finally 塊中不要丟擲任何異常:如果在 finally 塊中丟擲異常,可能會導致原始異常被掩蓋
-
不要在生產環境中使用
printStackTrace()
- ``printStackTrace()` 方法將異常的堆疊跟蹤資訊輸出到標準錯誤流中,這可能會暴露敏感資訊,如檔案路徑、使用者名稱、密碼等。
printStackTrace()
方法會將堆疊跟蹤資訊輸出到標準錯誤流中,這可能會影響程式的效能和穩定性。在高併發的生產環境中,大量的異常堆疊跟蹤資訊可能會導致系統崩潰或出現意外的行為。- 由於生產環境中往往是多執行緒、分散式的複雜系統,
printStackTrace()
方法輸出的堆疊跟蹤資訊可能並不完整或準確。
- 對於不打算處理的異常,直接使用 try-finally,不用 catch
- 記住早 throw 晚 catch 原則
- 只丟擲和方法相關的異常
- 切勿在程式碼中使用異常來進行流程控制
- 儘早驗證使用者輸入以在請求處理的早期捕獲異常
- 一個異常只能包含在一個日誌中
// 反例
log.debug("Using cache sector A");
log.debug("Using retry sector B");
// 正例
// 在多執行緒環境中,這兩行緊挨著的日誌程式碼中間可能會輸出很多其他的內容,導致問題查起來會很難受。
LOGGER.debug("Using cache sector A, using retry sector B");
- 將所有相關資訊儘可能地傳遞給異常
- 終止掉被中斷執行緒
// 反例
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {} //別這樣做
doSomethingCool();
}
// 正例
// 應該盡最大努力完成正在做的事情,並完成當前執行的執行緒,而不是忽略 InterruptedException
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
break;
}
}
doSomethingCool();
- 對於重複的 try-catch,使用模板方法