在java中,所有的對象都是繼承於Object類。Ojbect類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的。
在未重寫equals方法我們是繼承了object的equals方法,那里的 equals是比較兩個對象的內存地址,顯然我們new了2個對象內存地址肯定不一樣
- 對於值對象,==比較的是兩個對象的值
- 對於引用對象,比較的是兩個對象的地址
Object 默認的equals方法同==,一般來說我們的對象都是引用對象,要重寫equals方法。
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }
1 public static void main(String[] args) { 2 Object c=new Object(); 3 Object d=new Object(); 4 System.out.println(c.equals(d));//false 5 6 }
這個比較下,結果是false,也就是這兩個對象不一樣,但是有些業務,我們需要證明一個類的下面的實例對象時相等的,這時候我們就必須重寫equlas方法了。
如下代碼,我們新建一個對象Student,並重寫equals與hashCode方法
1 public class Student { 2 3 private int no; 4 5 private String name; 6 7 8 @Override 9 public boolean equals(Object o) { 10 if (this == o) return true; 11 if (o == null || getClass() != o.getClass()) return false; 12 13 Student student = (Student) o; 14 15 if (no != student.no) return false; 16 return !(name != null ? !name.equals(student.name) : student.name != null); 17 18 } 19 20 @Override 21 public int hashCode() { 22 int result = no; 23 result = 31 * result + (name != null ? name.hashCode() : 0); 24 return result; 25 } 26 27 public int getNo() { 28 return no; 29 } 30 31 public void setNo(int no) { 32 this.no = no; 33 } 34 35 public String getName() { 36 return name; 37 } 38 39 public void setName(String name) { 40 this.name = name; 41 } 42 }
1 Student a=new Student(); 2 Student b=new Student(); 3 System.out.println(a.equals(b));//ture
此時可以看出a、b對象相等.
hashCode方法也是可以用來比較兩個對象是否相等的。但是我們很少使用,應該說是很少直接使用。hashCode方法返回的是一個int值,可以看做是一個對象的唯一編碼,如果兩個對象的hashCode值相同,我們應該認為這兩個對象是同一個對象。
一般如果使用java中的Map對象進行存儲時,他會自動調用hashCode方法來比較兩個對象是否相等。
所以如果我們對equals方法進行了重寫,建議一定要對hashCode方法重寫,以保證相同的對象返回相同的hash值,不同的對象返回不同的hash值。
1、重寫equals方法時需要重寫hashCode方法,主要是針對Map、Set等集合類型的使用;
a: Map、Set等集合類型存放的對象必須是唯一的;
b: 集合類判斷兩個對象是否相等,是先判斷equals是否相等,如果equals返回TRUE,還要再判斷HashCode返回值是否ture,只有兩者都返回ture,才認為該兩個對象是相等的。
2、由於Object的hashCode返回的是對象的hash值,所以即使equals返回TRUE,集合也可能判定兩個對象不等,所以必須重寫hashCode方法,以保證當equals返回TRUE時,hashCode也返回Ture,這樣才能使得集合中存放的對象唯一。
個人感覺equals重寫,是站在使用的角度上考慮的:類設計者不希望通過內存地址來比較兩個對象是否相等,重寫這個equals方法,能夠方便的使用Collection<E>操作自定義對象E(Collection中很多方法涉及E.equals()的);而hashCode的重新,是方便Map<K,V>的使用,良好的自定義hashCode,會極大的提高Map的使用效率。
為啥說equals重新時,一定要重寫hashCode?感覺這么理解不知行不行:既然自定義類重寫了equals方法,說明類設計者不希望通過內存地址來比較兩個對象是否相等了。而Object的hashCode也是對象的內存地址,既然不希望通過地址比較對象,那么以內存地址作為hashCode也就沒有實際使用意義了,索性將自定義對象的hashCode方法也重寫了吧!