Java中equals、==和hashcode()
java中的數據類型,可分為兩類:基本數據類型的==比較的是值,復合數據類型的==比較的是內存地址
1.基本數據類型
也稱原始數據類型。byte,short,char,int,long,float,double,boolean
他們之間的比較:應用雙等號(==),比較的是他們的值。
2.復合數據類型(類)
當他們用"=="進行比較的時候,比較的是他們在內存中的存放地址,所以,除非是同一個new出來的對象,他們的比較后的結果為true,否則比較后結果為false。
3.equals()默認比較內存地址,除非重寫覆蓋equals()
圖片來源
JAVA當中所有的類都是繼承于Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行為是比較對象的內存地址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date,hashMap類,hashSet類等在這些類當中equals有其自身的實現,而不再是比較類在堆內存中的存放地址了。
對于復合數據類型之間進行equals比較,在沒有覆寫equals方法的情況下,他們之間的比較還是基于他們在內存中的存放位置的地址值的,因為Object的equals方法也是用雙等號"=="進行比較的,所以比較后的結果跟雙等號的結果相同。
下面代碼幫助理解:
解釋:程序在運行的時候會創建一個字符串緩沖池。使用s2 = “ronaldo” 這樣的表達式創建字符串的時候,程序首先會在這個String緩沖池中尋找相同值的對象,在第一個程序中,s1先被放到了池中,所以在s2被創建的時候,程序找到了具有相同值的 s1將s2引用為s1所引用的對象"ronaldo"
第二段程序中,使用了 new 操作符,告訴程序必須創建一個新的,不要到字符串緩沖里拿。于是一個新的"ronaldo"String對象被創建在內存中。他們的值相同,但是內存地址卻不同。
4.hashcode()
hashCode方法的主要作用是為了配合基于散列的集合一起正常運行,這樣的散列集合包括HashSet、HashMap以及HashTable。有些讀者誤以為默認情況下,hashCode返回的就是對象的存儲地址,這種看法是不全面的,確實有些JVM在實現時是直接返回對象的存儲地址,但大多時候并不是這樣,只能說可能存儲地址有一定關聯。那么可以直接根據hashcode值判斷兩個對象是否相等嗎?肯定是不可以的,因為不同的對象可能會生成相同的hashcode值。雖然不能根據hashcode值判斷兩個對象是否相等,但是可以直接根據hashcode值判斷兩個對象不等,如果兩個對象的hashcode值不等,則必定是兩個不同的對象。如果要判斷兩個對象是否真正相等,必須通過equals方法。
hash值不相等,那么兩個對象不相等,hash值相等,對象也不一定相等 也就是說對于兩個對象,如果調用equals方法(equals此時是比較內存)結果為true,則兩個對象的hashcode值必定相等; 如果equals方法得到的結果為false,則兩個對象的hashcode值不一定不同; 如果兩個對象的hashcode值不等,則equals方法得到的結果必定為false; 如果兩個對象的hashcode值相等,則equals方法得到的結果未知。某些情況下,程序員在設計一個類的時候為需要重寫equals方法,比如String類、hashMap類、hashSet類、hashTable類等,特別要注意的是:在重寫equals方法的同時,必須重寫hashCode方法。為何?
因為hashCode方法一般的規定是(參考文獻):
- 1.在 Java 應用程序執行期間,在對同一對象多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另一次執行,該整數無需保持一致。- 2.如果根據 equals(Object) 方法,兩個對象是相等的,那么對這兩個對象中的每個對象調用 hashCode 方法都必須生成相同的整數結果。- 3.如果根據 equals(java.lang.Object) 方法,兩個對象不相等,那么對這兩個對象中的任一對象上調用 hashCode 方法不 要求一定生成不同的整數結果。但是,程序員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。翻譯一下第二三點就是:hashCode()和equals()保持一致,如果equals方法返回true,那么兩個對象的hasCode()返回值必須一樣。如果equals方法返回false,hashcode可以不一樣,但是這樣不利于哈希表的性能,一般我們也不要這樣做。重寫equals()方法就必須重寫hashCode()方法的原因也就顯而易見了。假設兩個對象,重寫了其equals方法,其相等條件是屬性相等,就返回true。如果不重寫hashcode方法,其返回的依然是兩個對象的內存地址值,必然不相等。這就出現了equals方法相等,但是hashcode不相等的情況。這不符合hashcode的規則。這種情況會導致的嚴重問題。所以在hashMap之類的集合類需要通過重寫hashcode()和equals()來實現功能。如果不重寫hashcode()和equals()那么這個key用的就是Object的這兩個方法,然后hashcode就是指內存地址,equals判斷的是兩個對象是否堆中統一對象。重寫后我們看到hashcode和equals就只跟成員變量的值有關系了,倘若我們重新創建一個對象,雖然跟hashmap中的key分屬不同的堆內對象,但是他們的hashcode是一樣的,equals也是比較的是成員變量的值,而不再是內存地址。所以可以才能匹配的到。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java中equals、==和hashcode()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网晚报 | 12月22日 星期三 |
- 下一篇: HashMap(Java)