當(dāng)被問(wèn)到為什么要重寫(xiě)equals和hashcode方法

面試的時(shí)候老是會(huì)問(wèn)到為什么要重寫(xiě)equals和hashcode方法。其實(shí)這個(gè)問(wèn)題里面包含好幾個(gè)問(wèn)題,我們通過(guò)源碼一一拆解就知道了!

  1. equals() 比較的是什么?

  2. hashcode() 方法是什么?

  3. 為什么要重寫(xiě)equals()?

  4. 為什么要重寫(xiě)hashcode() 方法,不重寫(xiě)可以?

首先我們要知道equals() 和hashcode() 是基類(lèi) java.lang.Object自帶的方法。

public native int hashCode();

public boolean equals(Object obj) {

return (this == obj);

}

hashcode() 是一個(gè)本地方法,返回的是jdk根據(jù)對(duì)象的地址或者字符串或者數(shù)字算出來(lái)的int類(lèi)型的數(shù)值(解釋來(lái)自于百度百科)。equals()方法默認(rèn)比較的就是對(duì)象本身,其實(shí)就是內(nèi)存地址。

那么有一個(gè)問(wèn)題,如果new了兩個(gè)屬性值一樣的對(duì)象,它們對(duì)于java來(lái)說(shuō)是不equal的,因?yàn)閷?duì)于java來(lái)說(shuō)兩個(gè)對(duì)象指向的是兩個(gè)不同的內(nèi)存地址。但是一般我們希望如果對(duì)象的屬性值一樣,那么我們就判斷這兩個(gè)對(duì)象相等。 那么就需要重寫(xiě)equals()。

下面我設(shè)計(jì)一個(gè)User類(lèi),包含id和realName屬性。我認(rèn)為只要id和name相同,那么就認(rèn)為兩個(gè)對(duì)象 相等。
ps :重寫(xiě) toString() 和equals() ,建議用IDE自帶的工具來(lái)生成。

  public class User {
    private String id;
    private String realName;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getRealName() {
        return realName;
    }
    public void setRealName(String realName) {
        this.realName = realName;
    }
    public User(String id, String realName) {
        this.id = id;
        this.realName = realName;
    }
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", realName='" + realName + '\'' +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) &&
                Objects.equals(realName, user.realName);
    }
}
public class OverrideHashcode {
    public static void main(String[] args) {
       Set<User> data = new HashSet<>();
        User a = new User("1001","小葉檀");
        User b = new User("1001","小葉檀");
        data.add(a);
        data.add(b);
        System.out.println("沒(méi)有重寫(xiě)hashcode前:"+data.toString());
        System.out.println("兩個(gè)對(duì)象是否相等:"+(a.equals(b)));
    }
}

運(yùn)行后打印結(jié)果:
沒(méi)有重寫(xiě)hashcode前:[User{id='1001', realName='小葉檀'}, User{id='1001', realName='小葉檀'}]
兩個(gè)對(duì)象是否相等:true

在沒(méi)重寫(xiě)hashcode()時(shí),默認(rèn)是以對(duì)象的內(nèi)存地址來(lái)參與計(jì)算hash碼的。
因?yàn)閮?nèi)存地址不同,那么得到的hash碼也不一樣,那么對(duì)于hashset來(lái)說(shuō)就被認(rèn)為是兩個(gè)不同的對(duì)象。

兩個(gè)相同的實(shí)例卻有不同的hashcode, 這樣就有點(diǎn)違背hashset的原則了。
所以需要重寫(xiě)hashcode()。

@Override
    public int hashCode() {
        return Objects.hash(id, realName);
    }

重寫(xiě)完后再執(zhí)行main方法,發(fā)現(xiàn)set里面只有一個(gè)對(duì)象了。 大功告成!

總結(jié)

equals()默認(rèn)比較內(nèi)存地址,與業(yè)務(wù)而言意義不大,重寫(xiě)equals()為了結(jié)合業(yè)務(wù)體現(xiàn)對(duì)象的真實(shí)性。

hashcode()默認(rèn)是取的對(duì)象的內(nèi)存地址去計(jì)算散列碼,業(yè)務(wù)上認(rèn)為相同的實(shí)例所得到的hashcode卻不同。 重寫(xiě)hashcode()就是為了能運(yùn)用那些基于hash標(biāo)識(shí)對(duì)象唯一性的集合類(lèi)。

在這里估計(jì)就會(huì)有人問(wèn)到String的equals()默認(rèn)比較的就是里面的內(nèi)容,不是內(nèi)存地址。下一篇文章就整理跟String相關(guān)的面試題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容