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

Java 空指針異常防禦指南:從源頭消除 NPE

     編輯:Java 程式設計入門

NPE 兩大典型成因

  1. 引用空對象:調用 null.method() 或訪問 null.field
  2. 拆箱空值:將 Integer 等包裝類 null 賦給基本類型 int

分層防禦策略

1. 外部依賴返回值 —— 嚴格驗證

對第三方 API、數據庫查詢、工作流引擎等不可控來源:

// 集合類
if (CollectionUtils.isNotEmpty(list)) { ... }
if (MapUtils.isNotEmpty(map)) { ... }

// 字符串
if (StringUtils.isNotBlank(str)) { ... } // 同時檢查 null、""、空白字符

// Optional 模式 (Java 8+)
Optional.ofNullable(externalService.getData())
        .ifPresent(data -> process(data));

2. 內部創建對象 —— 契約式設計

  • 構造器/工廠方法中對必填參數做 Objects.requireNonNull()
  • 集合字段初始化為空集合而非 null:private List<Item> items = new ArrayList<>();
  • 對外暴露不可變視圖:return Collections.unmodifiableList(items);

3. Web 表單綁定對象 —— 框架層面處理

Spring MVC 等框架將空字符串綁定為 null 而非 ""。建議:

  • DTO 字段用 @NotBlank、@NotNull 校驗註解
  • 全局異常處理器統一返回 400 錯誤,避免 NPE 冒泡到 500

4. 工具類優於原生 API

關於性能的迷思

「過多判空影響性能」是微優化誤區。一次方法調用納秒級開銷,遠小於 NPE 導致的業務中斷、日志分析、應急修復成本。**可讀性與穩定性優先**,熱點路徑經 JIT 優化後幾乎零開銷。

現代 Java 最佳實踐

// 1. 參數校驗
public void save(UserDTO dto) {
    Objects.requireNonNull(dto, "用戶數據不能為空");
    String name = dto.getName();
    if (StringUtils.isBlank(name)) throw new IllegalArgumentException("姓名必填");
    ...
}

// 2. Optional 鏈式處理
public String getCityName(Long userId) {
    return userRepo.findById(userId)
            .map(User::getAddress)
            .map(Address::getCity)
            .orElse("未知城市");
}

// 3. Record 不可變數據載體 (Java 14+)
public record OrderDTO(@NotNull Long id, @NotBlank String item) {}

建立「不信任任何外部輸入、內部契約自證明、善用標準庫工具」的編碼習慣,可從根源上消除 90% 以上的 NPE。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
操作原生風險推薦替代
字符串分割"".split(",") 返回 [""]StringUtils.split(str, ",") 返回 []
集合判空list.size() > 0 拋 NPECollectionUtils.isNotEmpty(list)
對象比較a.equals(b) 拋 NPEObjects.equals(a, b)