String s = null;
System.out.println(s); // 輸出 "null" 字符串,不拋異常
// 後續 s.trim() → 拋 NullPointerException
對策:Objects.toString(obj, "") 或 String.valueOf(obj) 統一轉換,避免隱性 null 傳播。
// JSP/Controller 常見
if (request.getParameter("username").equals("admin")) // 參數缺失直接 NPE
out.println(session.getAttribute("user").toString()) // 屬性不存在 NPE
if (param != null && param.equals("val"))Objects.requireNonNull(obj, "msg")、Objects.equals(a, b) (null 安全)Optional.ofNullable(request.getParameter("p")).filter(v -> v.equals("x")).isPresent()@RequestParam(required=false)、@ModelAttribute 自動綁定。int age = Integer.parseInt(request.getParameter("age")); // 用戶輸入 "abc" → 崩潰
public static Integer parseIntSafe(String str, Integer defaultVal) {
try {
return (str != null && !str.trim().isEmpty()) ? Integer.parseInt(str.trim()) : defaultVal;
} catch (NumberFormatException e) {
log.warn("非法數字輸入: {}", str);
return defaultVal;
}
}
同理適用 Long、Double、BigDecimal。
String s = request.getParameter("code");
char c = s.charAt(5); // s 長度 < 6 → 異常
String sub = s.substring(2, 10); // 索引越界 → 異常
public static char charAtSafe(String s, int index, char defaultVal) {
return (s != null && index >= 0 && index < s.length()) ? s.charAt(index) : defaultVal;
}
public static String substringSafe(String s, int begin, int end) {
if (s == null) return "";
begin = Math.max(0, begin);
end = Math.min(s.length(), end);
return (begin < end) ? s.substring(begin, end) : "";
}
mvn dependency:tree / Gradle dependencies 分析衝突。WEB-INF/lib、伺服器 lib、共享庫目錄是否重複不同版本。-verbose:class 觀察類加載來源。module-info.java exports、opens。remove() 導致類加載器無法卸載 (PermGen/Metaspace OOM)。try (Resource r = acquire()) { ... } (JDBC、IO、Lock、HTTP Client 均實現 AutoCloseable)。ExecutorService 生命週期受控,shutdown() 优雅停機。try { threadLocal.set(val); ... } finally { threadLocal.remove(); }。| 檢查點 | 工具/習慣 |
|---|---|
| 所有外部輸入參數 | 判空 + 類型轉換安全封裝 |
| 所有字符串索引操作 | 長度檢查或安全工具方法 |
| 所有資源獲取點 | try-with-resources / AutoCloseable |
| 所有依賴引入 | 依賴樹分析、版本鎖定、BOM 管理 |
| 所有 ThreadLocal 使用 | finally remove() |
將這六類坑點內化為肌肉記憶,代碼穩健性將質的飛躍。