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

Java equals() 與 == 運算子深度解析:字符串常量池、new 操作與 intern() 實戰演示

     編輯:Java 相關知識

核心結論先行

比較對象== 比較equals() 比較
基本型別比較值N/A(基本型別無方法)
引用型別比較記憶體地址(是否同一物件)預設比較地址;String、Integer、Date 等類別重寫後比較「內容」

字符串常量池機制

JVM 為節省記憶體,維護一個字符串常量池(String Pool)。直接使用雙引號字面量(String s = "abc")建立字符串時:

  1. 先檢查池中是否已存在內容相同的字符串物件。
  2. 存在 → 直接返回該物件引用。
  3. 不存在 → 在池中建立新物件並返回引用。

因此:

String s1 = "Monday";
String s2 = "Monday";
System.out.println(s1 == s2); // true,同一池物件

new String() 強制建立新物件

使用 new 關鍵字時,繞過常量池,直接在堆中建立新物件:

String s1 = "Monday";
String s2 = new String("Monday");
System.out.println(s1 == s2);  // false,不同物件
System.out.println(s1.equals(s2)); // true,內容相同

intern() 手動入池

String.intern() 是 Native 方法,執行邏輯:

  1. 檢查常量池是否已有內容相同的字符串。
  2. 有 → 返回池中引用。
  3. 無 → 將當前字符串加入池並返回引用。
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern(); // 手動入池
System.out.println(s1 == s2); // true,現在指向同一池物件

記憶體圖解

String s1 = "Monday";          String s2 = new String("Monday");
┌──────────────┐               ┌──────────────┐     ┌──────────────┐
│ String Pool  │               │    Heap      │     │ String Pool  │
│  "Monday" ◄──┼───── s1       │  "Monday" ◄──┼──── s2           │
└──────────────┘               └──────────────┘     └──────────────┘
       ▲                              ▲
       │                              │
   s1 == s2 為 true              s1 == s2 為 false

最佳實踐建議

  1. 比較字符串內容永遠使用 equals(),除非你確定雙方皆來自常量池(如枚舉、單例模式)。
  2. 避免不必要的 new String(),直接用字面量享受常量池複用優勢。
  3. 大量動態字符串去重可考慮 intern(),但注意:JDK 6 常量池在 PermGen(易 OOM),JDK 7+ 移至 Heap,使用相對安全。
  4. 自定義類別覆寫 equals() 時務必遵循對稱性、傳遞性、一致性,並同時覆寫 hashCode(),否則在 HashMap/HashSet 中會失效。

常見面試陷阱題

String s1 = "a" + "b";      // 編譯期常量折疊 → "ab" 入池
String s2 = "ab";           // 字面量 → 池中同一物件
String s3 = new String("a") + new String("b"); // 運行期 new → 堆中新物件
String s4 = s3.intern();    // 手動入池

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true

總結

== 比較引用地址,equals() 比較邏輯內容(視類別實現而定)。字符串常量池與 intern() 是 JVM 優化字符串存儲的關鍵機制,理解其運作原理能避免 90% 的字符串比較 Bug,也是高頻面試必考點。

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