爲何重寫equals必定要重寫hashCode?

你們都知道,equals和hashcode是java.lang.Object類的兩個重要的方法,在實際應用中經常須要重寫這兩個方法,但至於爲何重寫這兩個方法不少人都搞不明白,如下是個人一些我的理解。java

這是Object類關於這兩個方法的源碼,能夠看出,Object類默認的equals比較規則就是比較兩個對象的內存地址。而hashcode是本地方法,java的內存是安全的,所以沒法根據散列碼獲得對象的內存地址,但實際上,hashcode是根據對象的內存地址經哈希算法得來的。算法

public native int hashCode();
public boolean equals(Object paramObject){
    return (this==paramObject);
}

上圖展現了Student類的重寫後的equals方法和hashcode方法,建議你們用eclipse自動生成,儘可能不要本身敲由於頗有可能會出錯。安全

如今有兩個Student對象:eclipse

Student s1=new Student("小明",18);ide

Student s2=new Student("小明",18);this

此時s1.equals(s2)必定返回truespa

/*
 * 
 * 
 * equals的使用
 * 
 * */
package com.tinaluo.java;

import java.awt.Color;

class Cat {
    private String name;
    private int age;
    private double weight;
    private Color color;

    public Cat(String name, int age, double weight, Color color) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.color = color;
    }

    /*
     * equals改寫後必須重寫hashCode()方法,對象相同則hashCode必須相同!
     * 一、equals()相同,則hashCode必須相等
     * 二、hashCode不相同等,則equals()必不相等
     * 
     * @see java.lang.Object#hashCode()
     */
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if(this==obj){
            return true;
        }
        if(obj==null){
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Cat cat = (Cat) obj;
        return name.equals(cat.name) && (age == cat.age)
                && (weight == cat.weight) && (color.equals(cat.color));
    }
}

public class InternalLoad {
    public static void main(String[] args) {
        Cat a = new Cat("java", 12, 21, Color.BLACK);
        Cat b = new Cat("C++", 12, 21, Color.WHITE);
        Cat c = new Cat("java", 12, 21, Color.BLACK);
        System.out.println(a.equals(b));
        System.out.println(a.equals(c));
        System.out.println(a.hashCode() == c.hashCode());
    }
}

假如只重寫equals而不重寫hashcode,那麼Student類的hashcode方法就是Object默認的hashcode方法,因爲默認的hashcode方法是根據對象的內存地址經哈希算法得來的,顯然此時s1!=s2,故二者的hashcode不必定相等。code

然而重寫了equals,且s1.equals(s2)返回true,根據hashcode的規則,兩個對象相等其哈希值必定相等,因此矛盾就產生了,所以重寫equals必定要重寫hashcode,並且從Student類重寫後的hashcode方法中能夠看出,重寫後返回的新的哈希值與Student的兩個屬性有關。對象

如下是關於hashcode的一些規定:blog

關鍵結論:

兩個對象相等,hashcode必定相等
兩個對象不等,hashcode不必定不等
hashcode相等,兩個對象不必定相等
hashcode不等,兩個對象必定不等

相關文章
相關標籤/搜索