Java中==與equals()及hashcode()三者之間的關(guān)系詳解
1.= =
=為賦值運算符,==為比較運算符,僅比較對象的內(nèi)存地址,無法比較真正意義上的相等!
JDK里的equals方法就是通過==來實現(xiàn)的比較對象的內(nèi)存地址
以Integer為例
Integer a = 127; Integer b = 127; System.out.println(a == b);//true Integer c = 128; Integer d = 128; System.out.println(c == d);//false
這里也是通過== 引出一個知識點,一個數(shù)值之差為啥導致結(jié)果不一樣?在[-128,127]的區(qū)間內(nèi)Integer a = 127;由于設(shè)計了緩存,而后的Integer b = 127;就是直接利用的緩存里的數(shù)值對象,所以通過==比較的結(jié)果為true,因為他們本質(zhì)還是一個數(shù)值對象
而Integer c = 128;Integer d = 128;就沒這樣幸運了,超過了緩存區(qū)間會重新new出對象,以至于兩者雖然數(shù)值相同但是地址不同
所以啊,==比較的是地址!也只是地址!
在前面==的基礎(chǔ)上,再來看equals()
2.equals()
以一個String類型的變量為例,當我們來使用equals()比較兩個對象時,結(jié)果肯定是false,因為equals()方法比較的是內(nèi)存地址,這里的person1,person2均是兩次new出來的,所以地址肯定是不相同的,而person1,person3指向同一空間地址一定是相同的
Person person1 = new Person("lyy");
Person person2 = new Person("lyy");
Person person3 = person1;
System.out.println(person1.equals(person2));//false
System.out.println(person1.equals(person3));//true
在不重寫的情況下,我們Ctrl+B看一下equals()的源碼:
public boolean equals(Object obj) {
return (this == obj);
}
顯而易見的是 (this = = obj)是該方法的核心,而 = = 又是兩個對象比較的方式,= = 嘛比的是內(nèi)存地址,懂的都懂噢
3.重寫equals()
記不記得你在刷面經(jīng)或者短視頻的時候經(jīng)常看到的一句話——比較兩個對象的內(nèi)容是否相等時我們要重寫equals()方法!
這是為何?那我們不妨來重寫一下equals()試試水
@Override
public boolean equals(Object obj){
if (this==obj){
return true;
}
if (obj==null||getClass()!= obj.getClass()){
return false;
}
Person person=(Person)obj;
return Objects.equals(name,person.name);
}
重寫過equals后,原有的兩者就已發(fā)生翻天覆地的變化,從原來的比較內(nèi)存地址——>比較對象內(nèi)容,這是一件很神奇的事情,因為實現(xiàn)了比較不同對象的相同或者不同內(nèi)容!
重寫之后:

具體是如何實現(xiàn)的呢?就像下面這樣…
4.equals()比較流程
下面我們來探索一下重寫的equals()是如何比較內(nèi)容的:
通過debug來深入理解一下

下面來看一下debug過程中變量情況

總的來說,通過debug,重寫equals()來比較不同變量的不同或者相同內(nèi)容得到了進一步論證!
5.hashcode()
我們在IDEA中通過CTRL+O的快捷鍵重寫hashcode()時它上面所屬的類是誰?

java.lang.Object!
顯而易見,該方法是Object類所定義的方法,作用是返回對象的哈希值返回值的類型為int(哈希值的作用是確定該對象在哈希表中的位置),曾經(jīng)有這樣一句流川千古的話:你必須在每個重寫equals()的類中重寫一遍hashcode()方法
如果不這樣做將會違反Object.hashcode()的一般約定,這會阻止lei與所有基于散列的集合(比如hashmap,hashset…)一起正常工作。為啥?因為hashmap,hashset等基于散列的集合中,會使用對象的hashcode值來確定該對象應該如何存儲到集合中,并且再次使用hashcode來定位對象在集合中的位置
那么
在一個類中重寫了equals()但沒重寫hashcode()會出現(xiàn)啥情況呢?
我們來通過一個例子試試水~
嘗試把對象都放入一個不能重復的set里,然后看集合的長度來判斷兩個對象是否相等!
public class equals_hashcode {
public static void main(String[] args) {
Person person1 = new Person("lyy");
Person person2 = new Person("lyy");
HashSet<Person> set = new HashSet<>();
set.add(person1);
set.add(person2);
System.out.println(set.size());
}
}
class Person {
public String name;
public Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}情況一:
當只重寫了equals()方法時運行的結(jié)果為2,由此得出兩個對象不相等!

情況二:
當既重寫了equals()和hashcode()后運行結(jié)果為1,所以兩個對象相等!

由此得出,對象相等的本質(zhì)是:
1.地址相同
2.哈希值相同(重寫hashcode的體現(xiàn))
這也不難聯(lián)系到之前的約定了,在比較對象是否相等的場景下,我們必須重寫equals()和hashcode()!
對象相等建立在==之上,equals(),hashcode()的雙重寫是對象相等的基本準則!
到此這篇關(guān)于Java中==與equals()及hashcode()三者之間的關(guān)系詳解的文章就介紹到這了,更多相關(guān)Java == equals() hashcode()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實現(xiàn)頁面多查詢條件必選的統(tǒng)一處理思路
這篇文章主要為大家介紹了java實現(xiàn)頁面多查詢條件必選的統(tǒng)一處理思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
JWT在OpenFeign調(diào)用中進行令牌中繼詳解
Feign是一個聲明式的Web Service客戶端,是一種聲明式、模板化的HTTP客戶端。而OpenFeign是Spring Cloud 在Feign的基礎(chǔ)上支持了Spring MVC的注解,如@RequesMapping等等,這篇文章主要給大家介紹了關(guān)于JWT在OpenFeign調(diào)用中進行令牌中繼的相關(guān)資料,需要的朋友可以參考下2021-10-10
Java實現(xiàn)京東聯(lián)盟API數(shù)據(jù)獲取功能
這篇文章介紹了Java獲取京東聯(lián)盟API數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
基于Java中throw和throws的區(qū)別(詳解)
下面小編就為大家?guī)硪黄贘ava中throw和throws的區(qū)別(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07

