Java 異常繼承自 Throwable,分兩大支系:
OutOfMemoryError),應用無需捕獲。從責任視角:Error→JVM、RuntimeException→程式設計師、Checked Exception→具體應用業務邏輯。
// 表現層(Action/Controller)統一入口
public void doAction(...) {
try {
bizService.doBusiness();
} catch (Exception e) {
if (e instanceof RuntimeException) {
// 記錄日誌、通知開發人員、返回友好錯誤頁
logger.error("程式設計錯誤", e);
notifyDevTeam(e);
return "error/500";
} else {
// 受檢異常:轉換為用戶可讀提示
return "error/bizError"; // 攜帶 e.getMessage()
}
}
}
Exception(受檢)cause 欄位 + initCause() + 重寫 getMessage()/printStackTrace() 遞歸輸出完整鏈路getCause() 兼容 JDK 1.4+public class ApplicationException extends Exception {
protected Throwable cause;
public ApplicationException() { super("Error occurred in application."); }
public ApplicationException(String msg) { super(msg); }
public ApplicationException(String msg, Throwable cause) { super(msg); this.cause = cause; }
public Throwable initCause(Throwable cause) { this.cause = cause; return cause; }
@Override public String getMessage() {
String msg = super.getMessage();
Throwable parent = this, child;
while ((child = getNestedException(parent)) != null) {
String msg2 = child.getMessage();
if (msg2 != null) msg = (msg != null) ? msg + ": " + msg2 : msg2;
if (child instanceof ApplicationException) break;
parent = child;
}
return msg;
}
// printStackTrace() 同理遞歸輸出 "Caused by:" 鏈路
protected Throwable getNestedException(Throwable t) { /* 反射獲取 cause 欄位 */ }
}
public class XXXBusinessException extends ApplicationException {
public XXXBusinessException(String msg) { super(msg); }
public XXXBusinessException(Throwable cause) { super(cause.getMessage(), cause); }
}
public void doBusiness() throws XXXBusinessException {
try {
executeStep1(); // 可能拋出 SQLException、RemoteException 等受檢異常
executeStep2();
} catch (Exception e) {
// 關鍵:過濾 RuntimeException,不包裝!
if (!(e instanceof RuntimeException)) {
throw new XXXBusinessException(e);
}
throw e; // 保持原樣拋出,讓表現層統一處理
}
}
錯誤示範:catch(Exception e){ throw new BizException(e); } 會吞沒 RuntimeException,導致程式設計錯誤偽裝成業務異常,掩蓋根因。
Exception(受檢),絕不繼承 RuntimeException。cause,重寫 getMessage/printStackTrace 遞歸輸出。ModuleBizException),細分錯誤碼(Enum)而非靠字符串。logger.error(msg, e) 保留完整堆疊,禁止 e.getMessage() 入庫。{code, message, traceId},前端據碼顯示國際化提示。