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

Java 字符串比較深度解析:== 與 equals 的本質區別與字符串池機制

     編輯:Java 程式設計入門

字符串比較是 Java 基礎中最高頻考點,也是新手最易踩坑的地方。本文從內存模型、字符串池、編譯器優化三個維度,徹底講透 == 與 equals() 的區別。

核心結論速覽

操作符比較內容適用場景
==引用地址(內存地址)判斷是否為同一對象
equals()字符序列內容判斷字符串值是否相等

經典案例完整演示


public class StringCompareDemo {
    public static void main(String[] args) {
        String a = "test";           // 常量池
        String b = "test";           // 常量池(同一引用)
        String c = new String("test"); // 堆對象
        String d = new String("test"); // 堆對象(不同引用)
        String e = a;                // 同引用
        String f = new String(a);    // 堆對象
        String g = a + "";           // 拼接產生新對象

        System.out.println("a==b: " + (a == b));  // true
        System.out.println("a==c: " + (a == c));  // false
        System.out.println("c==d: " + (c == d));  // false
        System.out.println("a==e: " + (a == e));  // true
        System.out.println("a==f: " + (a == f));  // false
        System.out.println("a==g: " + (a == g));  // false

        // equals 全部 true
        System.out.println("equals: " + (a.equals(b) && b.equals(c) && c.equals(d)
            && d.equals(e) && e.equals(f) && f.equals(g)));
    }
}

深度解析:為什麼結果這樣?

1. 字符串常量池

  • String a = "test":編譯期確定,存入常量池
  • String b = "test":編譯期發現常量池已有 "test",直接復用引用
  • 因此 a == b 為 true

2. new String() 強制創建堆對象

  • new String("test"):運行期在堆創建新對象,即使常量池有相同內容
  • c、d、f 互為不同對象,c == d 為 false

3. 變量賦值 vs 對象創建

  • String e = a:引用傳遞,指向同一對象 → a == e 為 true
  • String f = new String(a):顯式 new,新對象 → false

4. 字符串拼接的隱式 new

  • a + "":編譯器優化為 new StringBuilder().append(a).append("").toString()
  • 結果是新對象 → a == g 為 false

equals() 內部實現


// String.equals() 核心邏輯
public boolean equals(Object anObject) {
    if (this == anObject) return true;  // 同引用快速返回
    if (anObject instanceof String) {
        String another = (String) anObject;
        // 比較字符數組長度與內容
        return value.length == another.value.length
            && Arrays.equals(value, another.value);
    }
    return false;
}

Object.equals() 默認就是 ==,String 重寫實現內容比較。

實戰最佳實踐

  1. 比較內容永遠用 equals():"test".equals(input) 或 Objects.equals(a, b)(防空指針)
  2. 常量放左邊:"CONST".equals(var) 避免 var 為 null 拋 NPE
  3. intern() 手動入池:String s = new String("test").intern() 返回常量池引用,s == "test" 為 true
  4. 編譯期常量自動入池:final String s = "a" + "b" → "ab" 入池

JDK 版本差異提示

  • JDK 6:常量池在永久代
  • JDK 7+:常量池移至堆,intern() 性能提升
  • JDK 8+:永久代移除,元空間替代

總結

== 比地址,equals 比內容。字面量自動入池,new 強制新對象。拼接隱式 new,intern 手動入池。業務比較永遠用 equals,防空用 Objects.equals。

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