Java中的對象要怎樣才算相等

来源:https://www.cnblogs.com/harrymore/archive/2018/06/05/9141947.html
-Advertisement-
Play Games

一、引用相等性與對象相等性 1. 引用相等性 引用到堆上同一個對象的兩個引用是相等的,這就是引用的相等性。 如果想要知道兩個引用是否相等,可以使用==來比較變數上的位元組組合,如果引用到相同的對象,位元組組合也會一樣: 2. 對象相等性 堆上的兩個不同對象在意義上是相同的,這就是對象的相等性。 兩個對象 ...


一、引用相等性與對象相等性

1. 引用相等性

引用到堆上同一個對象的兩個引用是相等的,這就是引用的相等性。

1

如果想要知道兩個引用是否相等,可以使用==來比較變數上的位元組組合,如果引用到相同的對象,位元組組合也會一樣:

if (foo == bar){
    // 兩個引用都指向同一個對象
}

 

2. 對象相等性

堆上的兩個不同對象在意義上是相同的,這就是對象的相等性。

2

兩個對象相等的條件是它們的hashCode相等,而且調用以另一個對象為參數的equals時返回true:

if (foo.equals(bar) && foo.hashCode() == bar.hashCode()) {
    // 兩個引用指向同一個對象或者兩個對象是相等的 
}

我們知道所有的類都繼承自Object類,而Object類預設的equals方法是使用==進行比較:

public boolean equals(Object obj) {
    return (this == obj);
}

Object類的hashCode函數:

public native int hashCode();

是一個native函數,而且返回值類型是整形;實際上,該native方法將對象在記憶體中的地址作為哈希碼返回,可以保證不同對象的返回值不同。

因此,要比較兩個對象的相等性,首先需要重寫equals和hashCode方法。

 

二、equals()與hashCode()的規範與關係

1. equals()方法

JDK中說明瞭實現equals()方法應該遵守的約定:

1)自反性:x.equals(x)必須返回true。

2)對稱性:x.equals(y)與y.equals(x)的返回值必須相等。

3)傳遞性:x.equals(y)為true,y.equals(z)也為true,那麼x.equals(z)必須為true。

4)一致性:如果對象x和y在equals()中使用的信息都沒有改變,那麼x.equals(y)值始終不變。

5)非null:x不是null,y為null,則x.equals(y)必須為false。

 

2. hashCode()方法

JDK中對hashCode()方法的作用,以及實現時的註意事項做了說明:

1)hashCode()在哈希表中起作用,如java.util.HashMap。

2)如果對象在equals()中使用的信息都沒有改變,那麼hashCode()值始終不變。

3)如果兩個對象使用equals()方法判斷為相等,則hashCode()方法也應該相等。

4)如果兩個對象使用equals()方法判斷為不相等,則不要求hashCode()也必須不相等;但是開發人員應該認識到,不相等的對象產生不相同的hashCode可以提高哈希表的性能。

 

3. equals()與hashCode()的關係

通過上面兩點我們可以推出結論,如果有兩個對象a,b,如果有:

a.equals(b),則a.hashCode() == b.hashCode()為真,即兩個值相等的對象,他們的hashCode一定相等

反過來則不一定成立。

實際上在Java中,要證明兩個對象值相等,只要a.equals(b)為true就可以了。

 

三、hashCode的作用

總的來說,hashCode()在哈希表中起作用,如HashSet、HashMap等。

當我們向哈希表(如HashSet、HashMap等)中添加對象object時,首先調用hashCode()方法計算object的哈希碼,通過哈希碼可以直接定位object在哈希表中的位置(一般是哈希碼對哈希表大小取餘)。如果該位置沒有對象,可以直接將object插入該位置;如果該位置有對象(可能有多個,通過鏈表實現),則調用equals()方法比較這些對象與object是否相等,如果相等,則不需要保存object;如果不相等,則將該對象加入到鏈表中。

這也就解釋了為什麼equals()相等,則hashCode()必須相等。如果兩個對象equals()相等,則它們在哈希表(如HashSet、HashMap等)中只應該出現一次;如果hashCode()不相等,那麼它們會被散列到哈希表的不同位置,哈希表中出現了不止一次。

實際上,在JVM中,載入的對象在記憶體中包括三部分:對象頭、實例數據、填充。其中,對象頭包括指向對象所屬類型的指針和MarkWord,而MarkWord中除了包含對象的GC分代年齡信息、加鎖狀態信息外,還包括了對象的hashcode;對象實例數據是對象真正存儲的有效信息;填充部分僅起到占位符的作用, 原因是HotSpot要求對象起始地址必須是8位元組的整數倍。

 

四、參考

1. 《Head First Java(第二版)》

2. 詳解equals()方法和hashCode()方法


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.首先安裝mysql 具體教程可以參考https://blog.csdn.net/zhouzezhou/article/details/52446608 註意安裝產品的時候記得選擇MySQL Connector C,如圖 2.安裝好mysql之後,就開始配置,點擊項目->點擊項目屬性,如圖: 3. ...
  • 也許是最近模擬題打多了的緣故,我發現自己漸漸變得比較毒瘤起來,當然這也是有一定的好處的,因為從中我也學到了一些處理字元串的正確姿勢,今天我們就來講一 講如何用函數getline來讀入一整行字元串進行處理。或者他的一些變體。 首先我們先需要知道為什麼我們要學習這個函數,是這樣的,相信大家都應該知道以前 ...
  • Spring Boot 2.0 的推出又激起了一陣學習 Spring Boot 熱,就單從我個人的博客的訪問量大幅增加就可以感受到大家對學習 Spring Boot 的熱情,那麼在這麼多人熱衷於學習 Spring Boot 之時,我們自己也在思考: Spring Boot 為什麼帶來了這麼大的變革。 ...
  • c++文件的讀寫 1.文本方式的寫文件 3.二進位方式的寫文件 c++ include include using namespace std; int main(){ int ar[] = {11,232,123123,1223,455,4,4,5,56,4,33}; ofstream ofile ...
  • 一.首先在啟動類重寫SpringBootServletInitializer里的configure方法: 二.將springboot項目打成war包,使用maven打包需要修改pom文件,將預設的打為jar包修改成war: 也可以使用idea將構建好的項目打包,如圖: 三.和別的Spring項目一樣 ...
  • Java中的成員變數和局部變數一:成員變數;二:局部變數;三:成員變數與局部變數的區別; ...
  • 離 python2 退休還有 702 天,Python3.7 也將在 6 月份發佈正式版,你還記得 3.6 有哪些酷炫的特性嗎?來回顧一下。 可讀性更強的數字字面值 Python代碼在可讀性上做到了極致,被稱為是可執行偽代碼。然而,它還在不斷地改進,比如這個可讀性更好的數字字面值語法,就是方便程式員 ...
  • 如果某些條件滿足,才能做某件事情,而不滿足時不允許做,這就是所謂的判斷 不僅生活中有,在軟體開發中“判斷”功能也經常會用到 if判斷語句 if 要判斷的條件: 條件成立 if-else的使用格式 if 條件: 條件成立 else: 不滿足條件 if elif的功能 當xxx1滿足時,執行事情1,然後 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...