基本類型有默認值,編譯期強制賦值;引用類型默認 null,編譯器不攔截未初始化調用。所有 NPE 本質上都是「對 null 解引用」。
// 現場 1:直接使用請求參數
out.println(request.getParameter("username")); // 參數無 → null → println 輸出 "null" 但後續操作崩
// 現場 2:對 null 調用 equals/toString
String name = request.getParameter("username");
if (name.equals("root")) { ... } // name 為 null → NPE
// 現場 3:Session 失效後鏈式調用
String user = session.getAttribute("user").toString(); // 屬性無 → null → NPE
if (obj != null) { obj.method(); } 或 Optional.ofNullable(obj).ifPresent(...)String name = Optional.ofNullable(req.getParameter("name")).orElse("");統一異常處理模板:對所有可預期異常採用「記錄日誌 + 友好提示 + 降級/熔斷」三步走。
String s = request.getParameter("memberId"); // 用戶輸入 "T1082"
int id = Integer.parseInt(s); // 拋 NumberFormatException
| 策略 | 代碼 | 優點 | 缺點 |
|---|---|---|---|
| 默認值兜底 | catch → id = 0 | 簡單 | 下游邏輯可能誤判 0 為合法 ID |
| 拋業務異常 | catch → throw new BizException("會員ID格式錯誤") | 語義清晰、統一錯誤碼 | 需全鏈路異常處理機制 |
| 前端雙重校驗 | JS 正則攔截 + 後端再驗證 | 用戶體驗好、減少無效請求 | 不可替代後端校驗 |
推薦:後端統一用 @InitBinder 註冊自定義 Converter,轉換失敗拋統一 BindException,由 @ControllerAdvice 統一返回 JSON 錯誤。
substring(begin, end)、charAt(index)、getBytes()、valueOf(char[])。
public static String safeSubstring(String str, int begin, int end) {
if (str == null) return "";
int len = str.length();
if (begin < 0) begin = 0;
if (end > len) end = len;
if (begin >= end) return "";
return str.substring(begin, end);
}
所有業務代碼禁用原生 API,強制走工具類。IDE 可配置檢查規則禁止直接調用高危方法。
clean package)-verbose:class 觀察類加載來源mvn dependency:tree)try-with-resources,Sonar 規則禁止手動 close()單點修復治標,體系化防禦治本。成熟團隊應建立:
異常不可避免,但「不可控的異常」才是真正的敵人。