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

Java 字符串:null、空串("") 與 new String() 深度對比與判空最佳實踐

     編輯:Java 程式設計入門

一、三大核心概念本質區別

表達式類型內存結構長度含義
null引用值棧中引用指向 無對象N/A未指向任何對象
""String 對象堆/常量池中 長度為0 的字符串對象0存在但內容為空
new String()String 對象堆中 新創建 的長度為0對象0每次調用新建對象

二、內存模型圖解

棧 (Stack)                    堆
+----------+                 +------------------+
| str1 ──────────────────→  | "abc" (常量池)   |
+----------+                 +------------------+
| str2 = null              | (無對象)          |
+----------+                 +------------------+
| str3 = "" ─────────────→  | "" (常量池單例)  |
+----------+                 +------------------+
| str4 = new String("") →  | new String() 對象 |
+----------+                 +------------------+

關鍵點:

  • 引用變量在棧,對象在堆
  • "" 字面量編譯期進入字符串常量池,全局唯一
  • new String("") 運行期在堆創建新對象,繞過常量池

三、== vs equals() 實戰驗證

public class StringNullEmptyDemo {
    public static void main(String[] args) {
        String s1 = new String();   // 堆新對象 ""
        String s2 = null;           // 無對象
        String s3 = "";             // 常量池 ""
        
        System.out.println("s1==s2: " + (s1==s2));   // false (地址不同)
        System.out.println("s1.equals(s2): " + s1.equals(s2)); // false (null)
        System.out.println("s2==s3: " + (s2==s3));   // false
        System.out.println("s3.equals(s2): " + s3.equals(s2)); // false
        System.out.println("s1==s3: " + (s1==s3));   // false (堆 vs 常量池)
        System.out.println("s1.equals(s3): " + s1.equals(s3)); // true (內容相同)
    }
}

核心結論

  1. == 比較引用地址,equals() 比較字符內容
  2. 任何非 null 字符串 .equals("") 均為 true
  3. new String() 默認值為 "",非 null

四、判斷字符串是否為空的四種寫法(性能遞增)

❌ 寫法一:最直觀但最慢

if (str == null || str.equals(""))
  • 調用虛方法 equals(),有多態查找開銷
  • 字節碼指令多,JIT 優化難度大

✅ 寫法二:推薦標準(長度檢查)

if (str == null || str.length() == 0)
  • length() 是 final 方法,直接讀取 value.length 執行極快
  • JIT 易內聯優化
  • 兼容所有 JDK 版本

⚠️ 寫法三:JDK 6+ isEmpty()

if (str == null || str.isEmpty())
  • 本質調用 length() == 0,性能持平寫法二
  • 語義更清晰,但需 JDK 6+

❓ 寫法四:引用比較(有陷阱)

if (str == null || str == "")
  • 僅當右邊也是字面量 "" 或 String.intern() 後的對象才可靠
  • 不可用於 new String()、substring()、網絡/文件讀取的字符串
  • 生產環境禁用

五、空指針異常避坑指南

// ❌ 錯誤:先調用 equals 再判 null,若 str 為 null 直接 NPE
if (str.equals("") || str == null) { ... }

// ✅ 正確:短路原理,先判 null
if (str == null || str.equals("")) { ... }

// ✅ 更佳:長度檢查
if (str == null || str.length() == 0) { ... }

六、生產級工具類封裝建議

public final class StringUtils {
    private StringUtils() {}
    
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }
    
    public static boolean isBlank(CharSequence cs) {
        int len;
        if (cs == null || (len = cs.length()) == 0) return true;
        for (int i = 0; i < len; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) return false;
        }
        return true;
    }
    
    public static boolean isNotEmpty(CharSequence cs) { return !isEmpty(cs); }
    public static boolean isNotBlank(CharSequence cs) { return !isBlank(cs); }
}

七、總結速查表

場景推薦寫法備註
判空(含null)str == null || str.length() == 0全版本最優
判空白(含空格/換行)StringUtils.isBlank(str)Apache Commons / 自封裝
JDK 11+str.isBlank()原生支持 Unicode 空白字符
集合/數組判空CollectionUtils.isEmpty(list)同理先判 null 再判 size

記住:先判 null,再檢查長度,是處理字符串判空的鐵律。

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