首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 編程高頻最佳實踐:空指針防禦、API 陷阱規避、防禦性編程精華

     編輯:Java 綜合教學

Java 編程高頻最佳實踐精華

資深開發者總結的防禦性編程精華,涵蓋空指針預防、早期 JDK API 陷阱、魔術數字消除、意外賦值規避、集合安全檢查、final 設計原則,助你寫出健壯、可維護的生產級代碼。

1. 字串字面量優先:防空指針黃金法則

// ❌ 危險:variable 為 null 拋 NPE
if (variable.equals("literal")) { ... }

// ✅ 安全:字面量呼叫 equals,null 安全返回 false
if ("literal".equals(variable)) { ... }

原則:`equals`、`compareTo` 等非靜態方法,已知不為 null 的物件(字面量、常數、枚舉)放左邊。

2. 不盲目信任早期 JDK API 回傳值

// ❌ File.list():目錄回傳陣列,非目錄/IO錯誤回傳 null
String[] files = dir.list();
for (String f : files) { ... } // 可能 NPE

// ✅ 防禦性檢查
File[] files = dir.listFiles(); // 回傳 File[],空目錄回傳空陣列而非 null
if (files != null) {
    for (File f : files) { ... }
}
// 或用 Files.list(Path) (NIO.2) 回傳 Stream,更現代

3. 消除魔術數字 -1:語義化常數

// ❌ 硬編碼 -1:indexOf 未找到、read() 結束
if (str.indexOf("x") != -1) { ... }
while ((b = in.read()) != -1) { ... }

// ✅ 定義語義常數
private static final int NOT_FOUND = -1;
private static final int EOF = -1;
if (str.indexOf("x") != NOT_FOUND) { ... }
while ((b = in.read()) != EOF) { ... }

效益:語義自文檔化、未來 JDK 變更僅需修改常數定義、IDE 重構安全。

4. 避免意外賦值:Yoda 條件或編譯器輔助

// ❌ 易手滑寫成 =:意外賦值且條件永遠為 true
if (x = 5) { ... }

// ✅ Yoda 條件:常數在左,誤寫 = 編譯報錯
if (5 == x) { ... }

// ✅ 現代 IDE + 編譯器警示:-Xlint:assignment 或 SonarQube 規則

5. 集合/陣列雙重檢查:非空且非空

// ❌ 僅檢查 null,空集合仍進入迴圈浪費
if (list != null) { for (Item i : list) ... }

// ✅ 標準防禦模式
if (list != null && !list.isEmpty()) { ... }
// 或 Java 8+
if (CollectionUtils.isNotEmpty(list)) { ... } // Spring/Apache Commons

6. 方法預設 final:封裝不可變行為

public class BaseService {
    // 明確不想被覆寫的方法加 final
    public final void auditLog(String msg) { ... }
    
    // 故意開放擴展的方法不加 final
    protected void doBusiness() { ... }
}

效益:防止子類意外破壞核心邏輯、JIT 編譯器可內聯優化、語義明確傳達設計意圖。

綜合防禦性編程檢查清單

  1. 所有公開方法入參非空檢查(`Objects.requireNonNull`、斷言、Guava `Preconditions`)。
  2. 回傳集合/陣列優先回傳空集合/空陣列而非 null(消除調用端判空)。
  3. 不可變物件優先(`final` 欄位、無 setter、防禦性複製)。
  4. 資源用 `try-with-resources` 確保釋放。
  5. 異常處理:捕獲具體異常、保留堆疊、包裝業務異常拋出、避免吞噬異常。

將這些最佳實踐內化為肌肉記憶,能顯著降低線上故障率,提升代碼審查通過率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved