最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文讀懂 Java 中的 ==、equals () 與 hashCode ()原理與避坑指南

 更新時間:2025年09月05日 10:49:28   作者:凜冬君主  
在 Java 開發(fā)中,==、equals()?和?hashCode()?是處理對象比較和哈希計算的核心元素,理解它們之間的區(qū)別與聯(lián)系對編寫高質(zhì)量代碼至關(guān)重要,本文給大家介紹Java 中的 ==、equals()與hashCode()原理,感興趣的朋友一起看看吧

在 Java 開發(fā)中,==、equals() 和 hashCode() 是處理對象比較和哈希計算的核心元素,理解它們之間的區(qū)別與聯(lián)系對編寫高質(zhì)量代碼至關(guān)重要。

一、== 運算符

== 是 Java 中的比較運算符,用于比較兩個值是否相等,其行為取決于比較的是基本類型還是引用類型:

1. 比較基本數(shù)據(jù)類型

對于 int、doublechar 等基本類型,== 比較的是實際存儲的值

int a = 10;
int b = 10;
System.out.println(a == b); // true,值相等
double c = 3.14;
double d = 3.14;
System.out.println(c == d); // true

2. 比較引用數(shù)據(jù)類型

對于對象(引用類型),== 比較的是對象在內(nèi)存中的地址(即是否為同一個對象):

因為java是值傳遞,這里可能是地址的副本進(jìn)行比較,根據(jù)這個副本也可以修改對象。

但是,這種比較不關(guān)心變量是否相同,只關(guān)心引用的對象是否相同。

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false,兩個不同的對象,地址不同
String s3 = s1;
System.out.println(s1 == s3); // true,指向同一個對象

注意點

  • 基本類型的包裝類(如 Integer、Double)使用 == 時,同樣比較地址而非值(除非觸發(fā)常量池緩存機(jī)制)
  • 基本數(shù)據(jù)類型不能與null比較,因為基本數(shù)據(jù)類型就沒有null這個值。
  • null == null 結(jié)果為 true,任何對象與 null 用 == 比較都為 false

(1)基本類型 vs 包裝類(==比較)

  • 包裝類會自動拆箱為基本類型,比較的是值。
    例:int a = 5; Integer b = 5; System.out.println(a == b); // true

(2)包裝類 vs 包裝類(==比較)

  • 比較的是對象的引用地址(是否為同一個對象),而非值。
  • 注意:Java 對Integer[-128, 127]范圍內(nèi)有緩存機(jī)制,超出此范圍會創(chuàng)建新對象。
    例 1:Integer a = 100; Integer b = 100; System.out.println(a == b); // true(使用緩存)
    例 2:Integer a = 200; Integer b = 200; System.out.println(a == b); // false(新對象)
  • 當(dāng)其中一個為new Integer(1)時,是強(qiáng)制顯式創(chuàng)建一個對象,這里會開辟一個新的對象,即使緩存中有也不會使用。這時候比較就是false

二、equals () 方法

equals() 是 Object 類定義的實例方法,用于判斷兩個對象是否 "相等",默認(rèn)行為與 == 一致,比較的是對象的內(nèi)存地址(即是否為同一個對象)。

1. 默認(rèn)實現(xiàn)(Object 類中)

public boolean equals(Object obj) {
    return (this == obj); // 本質(zhì)就是用 == 比較地址
}

2. 重寫后的常見實現(xiàn)

多數(shù)類會重寫 equals() 方法,使其比較對象的內(nèi)容而非地址,例如 String 類:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // true,內(nèi)容相同
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
System.out.println(list1.equals(list2)); // true,兩個空列表內(nèi)容相同

3. 重寫 equals () 的規(guī)范

重寫 equals() 時需遵循以下規(guī)則(來自《Effective Java》):

  • 自反性x.equals(x) 必須返回 true
  • 對稱性:若 x.equals(y) 為 true,則 y.equals(x) 也必須為 true
  • 傳遞性:若 x.equals(y) 和 y.equals(z) 為 true,則 x.equals(z) 也必須為 true
  • 一致性:多次調(diào)用 x.equals(y) 應(yīng)返回相同結(jié)果(前提是對象未被修改)
  • 非空性x.equals(null) 必須返回 false

4. 重寫示例(自定義類)

public class User {
    private String id;
    private String name;
    // 構(gòu)造方法、getter、setter 省略
    @Override
    public boolean equals(Object o) {
        // 1. 自身判斷
        if (this == o) return true;
        // 2. 類型判斷
        if (o == null || getClass() != o.getClass()) return false;
        // 3. 內(nèi)容比較
        User user = (User) o;
        return Objects.equals(id, user.id) && 
               Objects.equals(name, user.name);
    }
}

注意點

  • 若調(diào)用者是null(如null.equals(obj)):必拋空指針異常。
  • 若參數(shù)是null(如obj.equals(null)):返回false(因為null不是任何對象的實例)。
  • 如果兩個對象通過equals()比較返回true,那么它們的hashCode()必須返回相同的值;反之,hashCode()不同的對象,equals()必須返回false。

三、hashCode () 方法

hashCode() 也是 Object 類的方法,返回一個 int 類型的哈希值,主要用于哈希表(如 HashMap、HashSet)中快速定位對象。

1. 基本作用

  • 哈希值用于確定對象在哈希表中的存儲位置
  • 提高哈希表的查找效率(理想情況下,不同對象應(yīng)具有不同哈希值)

2. 默認(rèn)實現(xiàn)

Object 類的 hashCode() 返回對象的內(nèi)存地址轉(zhuǎn)換后的整數(shù)(不同 JVM 實現(xiàn)可能不同)。

3. 重寫原則

關(guān)鍵規(guī)則如果兩個對象通過 equals() 比較相等,則它們的 hashCode() 必須返回相同的值。反之則不成立(不同對象也可能有相同哈希值,即哈希沖突)。

這是因為哈希表在判斷對象是否存在時,會先通過哈希值定位,再用 equals() 精確比較。若違反此規(guī)則,會導(dǎo)致哈希表無法正常工作:

// 反例:equals相等但hashCode不同
class BadExample {
    private int value;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BadExample that = (BadExample) o;
        return value == that.value;
    }
    @Override
    public int hashCode() {
        return (int) (Math.random() * 1000); // 錯誤實現(xiàn):相同對象可能返回不同哈希值
    }
}

4. 正確的重寫實現(xiàn)

通常結(jié)合對象中參與 equals() 比較的字段來計算哈希值:

@Override
public int hashCode() {
    // 使用 Objects.hash() 簡化實現(xiàn)
    return Objects.hash(id, name);
}
// 等價于手動計算
@Override
public int hashCode() {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    return result;
}

使用 31 是因為它是一個質(zhì)數(shù),能減少哈希沖突,且 31 * i 可以被優(yōu)化為 (i << 5) - i,提高計算效率。

四、三者之間的關(guān)系總結(jié)

  1. == 與 equals()

    • 未重寫 equals() 時,兩者功能一致(比較地址)
    • 重寫 equals() 后,== 仍比較地址,equals() 比較內(nèi)容
  2. equals() 與 hashCode()

    • 核心約定:equals() 為 true → hashCode() 必須相等
    • 反之不成立:hashCode() 相等 → equals() 不一定為 true(哈希沖突)
    • 實際應(yīng)用:在哈希集合中,先通過 hashCode() 定位,再用 equals() 確認(rèn)
  3. 使用場景

    • 比較基本類型 → 用 ==
    • 比較對象地址 → 用 ==
    • 比較對象內(nèi)容 → 用 equals()
    • 自定義類用于哈希表 → 必須同時重寫 equals() 和 hashCode()

五、常見面試題解析

  • 為什么重寫 equals () 必須重寫 hashCode ()?
    • 答:為了保證希表(如 哈HashMap)的正確性。如果兩個對象 equals 相等但 hashCode 不同,會導(dǎo)致它們在哈希表中被存儲在不同位置,從而出現(xiàn) "相同對象卻被視為不同" 的情況。
  • String 類的 == 和 equals () 有什么區(qū)別?
    • 答:== 比較對象地址,equals() 比較字符串內(nèi)容。由于字符串常量池的存在,"abc" == "abc" 為 true,但 new String("abc") == new String("abc") 為 false。
  • Integer 類型用 == 比較時要注意什么?
    • 答:Integer 對 -128~127 范圍的值有緩存,因此 Integer a = 100; Integer b = 100; a == b 為 true,但超出此范圍則為 false,應(yīng)始終用 equals() 比較值。

到此這篇關(guān)于一文讀懂 Java 中的 ==、equals () 與 hashCode ()原理與避坑指南的文章就介紹到這了,更多相關(guān)java ==、equals () 與 hashCode ()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot?vue接口測試定義編輯功能的實現(xiàn)

    springboot?vue接口測試定義編輯功能的實現(xiàn)

    這篇文章主要為大家介紹了springboot?vue接口測試定義編輯功能的實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • eclipse配置tomcat10的詳細(xì)步驟總結(jié)

    eclipse配置tomcat10的詳細(xì)步驟總結(jié)

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著eclipse配置tomcat10的詳細(xì)步驟展開,文中有非常詳細(xì)的介紹及圖文示例,需要的朋友可以參考下
    2021-06-06
  • 重寫hashCode()和equals()方法詳細(xì)介紹

    重寫hashCode()和equals()方法詳細(xì)介紹

    這篇文章主要介紹了重寫hashCode()和equals()方法詳細(xì)介紹,涉及重寫equals()方法,重寫hashCode()方法,重寫equals()而不重寫hashCode()的風(fēng)險等相關(guān)內(nèi)容的介紹,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • JFileChooser實現(xiàn)對選定文件夾內(nèi)圖片自動播放和暫停播放實例代碼

    JFileChooser實現(xiàn)對選定文件夾內(nèi)圖片自動播放和暫停播放實例代碼

    這篇文章主要介紹了JFileChooser實現(xiàn)對選定文件夾內(nèi)圖片自動播放和暫停播放實例代碼,需要的朋友可以參考下
    2017-04-04
  • Java選擇排序和垃圾回收機(jī)制詳情

    Java選擇排序和垃圾回收機(jī)制詳情

    這篇文章主要介紹Java選擇排序和垃圾回收機(jī)制,創(chuàng)建對象就會占據(jù)內(nèi)存,如果程序在執(zhí)行過程中不能再使用某個對象,這個對象是徒耗內(nèi)存的垃圾,下面來看看文章具體內(nèi)容吧
    2021-10-10
  • Java處理InterruptedException異常的理論與實踐

    Java處理InterruptedException異常的理論與實踐

    在使用Java的過程中,有個情景或許很多人見過,您在編寫一個測試程序,程序需要暫停一段時間,于是調(diào)用 Thread.sleep()。但是編譯器或 IDE 報錯說沒有處理檢查到的 InterruptedException。InterruptedException 是什么呢,為什么必須處理它?下面跟著小編一起來看看。
    2016-08-08
  • 解析spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class

    解析spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class

    這篇文章主要介紹了spring事務(wù)管理@Transactional為什么要添加rollbackFor=Exception.class,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • RocketMQ根據(jù)Tag進(jìn)行消息過濾

    RocketMQ根據(jù)Tag進(jìn)行消息過濾

    消費者訂閱了某個主題后,Apache RocketMQ 會將該主題中的所有消息投遞給消費者。若消費者只需要關(guān)注部分消息,可通過設(shè)置過濾條件在 Apache RocketMQ 服務(wù)端進(jìn)行過濾,只獲取到需要關(guān)注的消息子集,避免接收到大量無效的消息
    2023-02-02
  • Java中final、static關(guān)鍵字與方法的重寫和繼承易錯點整理

    Java中final、static關(guān)鍵字與方法的重寫和繼承易錯點整理

    這篇文章主要給大家介紹了關(guān)于Java中final、static關(guān)鍵字與方法的重寫和繼承易錯點的相關(guān)資料,在Java編程中final關(guān)鍵字用于限制方法或類的進(jìn)一步修改,final方法不能被子類重寫,而static方法不可被重寫,只能被遮蔽,需要的朋友可以參考下
    2024-10-10
  • Java解析JSON的六種方案

    Java解析JSON的六種方案

    這篇文章介紹了 6 種 JSON 解析方案,包括 Jackson、Gson、FastJSON、JsonPath、、手動解析,分別闡述了它們的功能特點、代碼示例、高級功能、優(yōu)缺點及適用場景,感興趣的小伙伴跟著小編一起來看看吧
    2025-01-01

最新評論

游戏| 玉门市| 米脂县| 肥城市| 固原市| 改则县| 剑阁县| 安陆市| 英吉沙县| 合水县| 安平县| 庆云县| 金昌市| 乐亭县| 上蔡县| 延安市| 佛坪县| 武穴市| 天祝| 黎平县| 福建省| 浦县| 富锦市| 伊通| 南召县| 理塘县| 永寿县| 井研县| 临邑县| 敖汉旗| 天气| 双峰县| 西峡县| 蛟河市| 东辽县| 博客| 平乡县| 石河子市| 延边| 精河县| 原阳县|