關於異常處理的幾點建議
一、原則
捕獲異常必須處理異常,要麽轉換成對應文案返回給調用方,要麽顯式拋出異常給調用方,提醒調用方捕獲處理,顯式拋出異常時,源異常信息和異常Trace棧信息必須打印出來或者拋給調用方。
二、不符合規範的編碼風格
// 不符規範 - 示例一
try {
/* ... */
} catch (Exception e) {
log.info("context"); //-導致結果:異常信息丟失
}
// 不符規範 - 示例二
try {
/* ... */
} catch (Exception e) {
log.info(e.getMessage()); //-導致結果:異常Trace棧信息丟失,無法定位詳細出錯位置。
}
// 不符規範 - 示例三
try {
/* ... */
} catch (Exception e) {
throw new RuntimeException("context"); //-導致結果:異常信息和異常Trace棧信息丟失
}
三、符合規範的編碼風格
//正確處理-示例一
try {
/* ... */
} catch (Exception e) {
log.info(e);//業務可降級,允許失敗用info,業務不允許失敗,必須用log.error()以便統計報警
}
//正確處理-示例二
try {
/* ... */
} catch (Exception e) {
throw new RuntimeException(e); //攜帶源異常信息拋給上層業務處理。
throw new RuntimeException("業務異常自定義錯誤信息",e); //攜帶源異常信息拋給上層業務處理,並追加定義業務異常錯誤信息。推薦此方法。
}
//正確處理-示例三
try {
/* ... */
} catch (RuntimeException e) {
log.info(e);
doSomething();//捕捉特定異常,此類異常能預料,且提供了補償機制
} catch (Exception e) {
//將異常轉換為指定異常,此處可以使用業務自定義異常
throw new BussiException(e);//攜帶源異常信息拋給上層業務處理。
throw new RuntimeException(e);//攜帶源異常信息拋給上層業務處理。
throw new RuntimeException("業務異常自定義錯誤信息",e); //攜帶源異常信息拋給上層業務處理,並追加定義業務異常錯誤信息。推薦此方法。
}
四、常見可自動降級異常
InterruptedException, NumberFormatException, ParseException and MalformedURLException 等異常,有時候是可以自動降級的。
比如:我們將一個字符串轉換為數字,當傳入的字符串是非數字類,我們可以給默認值0,但業務必須對0這個值有感知,業務允許0是合法的業務數值,則可以視業務處理成功。如果業務不允許該數值為0,則必須迅速失敗並返回錯誤文案。
int myInteger;
try {
myInteger = Integer.parseInt(myString);
} catch (NumberFormatException e) {
// 出現該異常時,業務可接受指定默認值0
myInteger = 0;
}
最後,再一次提醒: 不要忽略異常不處理!否則你的程序將會莫名其妙出錯,卻無從查起。
關於異常處理的幾點建議