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

Java String 判斷 null/空值與記憶體位址比較完全指南

     編輯:Java 相關知識

常見錯誤寫法與風險

錯誤寫法問題後果
if (str == "")比較記憶體位址,非內容永遠為 false,邏輯失效
if (str.equals(""))str 為 null 時拋 NPE程式崩潰
if (!str.equals(""))同上程式崩潰

正確判斷空值/空字串

寫法一:長度檢查(推薦,可讀性佳)

if (str != null && str.length() != 0) {
    // 非空且非空字串
}

寫法二:常量在前(避免 NPE)

if (!"".equals(str)) {
    // str 為 null 時回傳 false,不拋異常
}

寫法三:Java 6+ isEmpty()

if (str != null && !str.isEmpty()) { ... }

寫法四:Apache Commons Lang / Spring 工具類

org.apache.commons.lang3.StringUtils.isNotBlank(str); // null、""、"   " 皆視為空白
org.springframework.util.StringUtils.hasText(str);    // 同樣語意

完整測試範例

public class StringNullEmptyDemo {
    public static void main(String[] args) {
        test(null);
        test("");
        test(" ");
        test("hello");
    }

    static void test(String value) {
        if (value == null) {
            System.out.println("value is null");
        } else if ("".equals(value)) {
            System.out.println("value is empty string");
        } else {
            System.out.println("value = \"" + value + "\"");
        }

        // 錯誤示範:永遠不會進入
        if (value == "") {
            System.out.println("ERROR: this line never prints");
        }
    }
}

輸出結果

value is null
value is empty string
value = " "
value = "hello"

String 記憶體位址比較(== vs equals)深度解析

public class StringAddressDemo {
    public static void main(String[] args) {
        String a = "hello";
        String b = "he";
        String c = a.substring(0, 2);        // 執行期產生新物件
        System.out.println(b.equals(c)); // true
        System.out.println(b == c);      // false

        String d = new String("hello");    // 堆上新物件
        System.out.println(d.equals(a)); // true
        System.out.println(d == a);      // false

        String e = new StringBuilder("hello").toString(); // 執行期新物件
        System.out.println(e == a);      // false

        String f = "hello";                // 常數池同一個
        System.out.println(f == a);      // true
        System.out.println(f == "hello"); // true
        System.out.println(f == "hell" + "o"); // true(編譯期常數摺疊)

        String g = b + "llo";              // 執行期拼接 → 新物件
        System.out.println(g == f);      // false

        String h = "he" + "llo";           // 編譯期常數摺疊 → 常數池
        System.out.println(h == f);      // true
    }
}

三大核心規則總結

  1. new String() 永遠在堆上建立新物件,不進常數池,多次 new 互不共享。
  2. 編譯期常數表達式(字面值 + 字面值)會摺疊,結果進常數池,共享同一實例。
  3. 執行期運算(substring、StringBuilder、變數拼接)產生新物件,不進常數池,不共享。

最佳實務建議

  • 比較內容永遠用 equals() 或 Objects.equals()
  • 判斷空值用 StringUtils.isBlank() 或 str == null || str.isEmpty()
  • 極少數效能敏感場景(如緩存 Key 比對)才考慮 ==,且必須確保字串來源為常數池或經過 intern()
  • 避免不必要的 new String("literal"),直接用字面值

結語

String 看似簡單,實則涉及常數池、堆記憶體、編譯期優化等 JVM 核心機制。掌握「內容比較用 equals、位址比較用 ==、空值判斷用工具類」三原則,並理解常數摺疊與執行期建立物件的差異,能避開 99% 的 String 相關 Bug。

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