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

Java == 與 equals() 深度解析:從內存模型到最佳實踐

     編輯:Java 相關知識

核心結論先行

比較方式基本類型引用類型
==比較值比較堆內存地址(引用是否指向同一對象)
equals()不可用(編譯錯誤)默認比較地址;常用類已重寫比較內容(String、Integer、Date 等)

一、內存模型視角理解


// 基本類型:棧內存直接存值
int a = 10;
int b = 10;
a == b; // true,值相等

// 引用類型:棧存引用,堆存對象
Person p1 = new Person("張三", 25);
Person p2 = new Person("張三", 25);
Person p3 = p1;

p1 == p2; // false,不同堆對象,地址不同
p1 == p3; // true,同一引用指向同一堆對象

二、Object.equals() 默認實現與重寫契約

// Object 源碼
public boolean equals(Object obj) {
    return (this == obj); // 默認就是比較地址
}

重寫規範(自反性、對稱性、傳遞性、一致性、非空性):

  1. 若重寫 equals(),必須重寫 hashCode(),保證相等對象哈希碼相等(HashMap/HashSet 正確工作前提)。
  2. 推薦使用 IDE 自動生成或 Apache Commons Lang EqualsBuilder。

三、經典類庫重寫行為對比

// String:比較字符序列
String s1 = "hello";
String s2 = "hello";        // 常量池同一對象
String s3 = new String("hello"); // 堆新對象

s1 == s2;        // true
s1 == s3;        // false
s1.equals(s2);   // true
s1.equals(s3);   // true

// Integer:-128~127 緩存池
Integer i1 = 100;
Integer i2 = 100;    // 緩存池同一對象
Integer i3 = 200;
Integer i4 = 200;    // 超出緩存範圍,新對象

i1 == i2;  // true
i3 == i4;  // false
i3.equals(i4); // true

四、自定義類正確重寫範例

public class Person {
    private String name;
    private int age;

    // 構造器、getter/setter 省略

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;           // 同一引用快速返回
        if (o == null || getClass() != o.getClass()) return false; // 類型檢查
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name); // 內容比較
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age); // 與 equals 使用同一字段
    }
}

五、實戰避坑指南

  1. 空指針安全:"constant".equals(variable) 避免變量為 null 時拋 NPE。
  2. 集合比較:List/Set 已重寫 equals 比較元素內容而非順序/引用。
  3. 避免破壞對稱性:不要在 equals 中與非本類對象比較(如與 String 比較)。
  4. 性能優化:先比較基本類型字段,後比較引用類型;常用字段優先。

六、總結建議

  • 基本類型:只用 ==。
  • 引用類型比較內容:優先使用 equals(),前提是類已正確重寫(JDK 標準庫、主流第三方庫均已重寫)。
  • 引用類型比較同一性:用 ==(如枚舉、單例、緩存池對象)。
  • 自定義實體類:必須成對重寫 equals() 和 hashCode(),基於業務主鍵或唯一業務字段比較。

深入理解 == 與 equals 的語義差異與底層機制,是編寫正確、高效 Java 代碼的基石,也是面試高頻考點。

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