轉自:http://www.sunxin.org/forum/thread/19720.htmlhtml
先談equals。 equals是Object類提供的方法之一,衆所周知,每個java類都繼承自Object類, 因此說每個對象都有equals這個方法。而咱們在用這個方法時卻通常都重寫這個方法,why?
Ok,先看一個Object類中equals()方法的源代碼:java
public boolean equals(Object obj) { return (this == obj); }
從這個方法中能夠看出,只有當一個實例等於它自己的時候,equals()纔會返回true值。通俗地說,此時比較的是兩個引用是否指向內存中的同一個對象,也能夠稱作是否實例相等。而咱們在使用equals()來比較兩個指向值對象的引用的時候,每每但願知道它們邏輯上是否相等,而不是它們是否指向同一個對象——這就是咱們一般重寫這個方法的緣由。程序員
在程序員之家論壇中有這樣一篇文章《全面理解Java中的String數據類型》(連接http://www.phome.asia/forum/thread/19667.html) ,在這篇文章中,String s1 = new String(「kvill」),String s2 = new String(「kvill」); s1.equals(s2)爲ture,說明String類中已經重寫了equals()方法,若是不重寫equals()方法,那麼s1.equals(s2)默認比較兩個對象所指向的內存地址是否相同,返回值必然爲false。性能
重寫equals()方法看起來很是簡單,可是有許多改寫的方式會致使錯誤,而且後果很是嚴重。要想正確改寫equals()方法,你必需要遵照它的通用約定。下面是約定的內容,來自java.lang.Object的規範,equals方法實現了等價關係,如下是要求遵循的5點,這5點都是當年數學的概念啊……,呵呵,且看:this
1. 自反性:對於任意的引用值x,x.equals(x)必定爲true。 spa
2. 對稱性:對於任意的引用值x 和 y,當x.equals(y)返回true時,y.equals(x)也必定返回true。 code
3. 傳遞性:對於任意的引用值x、y和z,若是x.equals(y)返回true,而且y.equals(z)也返回true,那麼x.equals(z)也必定返回true。htm
4. 一致性:對於任意的引用值x 和 y,若是用於equals比較的對象信息沒有被修改,屢次調用x.equals(y)要麼一致地返回true,要麼一致地返回false。對象
5. 非空性:對於任意的非空引用值x,x.equals(null)必定返回false。繼承
瞭解了equals重寫,咱們再看hashCode()這個方法,hashcode()這個方法也是從object類中繼承過來的,在object類中定義以下:
public native int hashCode();
說明是一個本地方法,它的實現是根據本地機器相關的。再看它比較「官方」的詳細說明:hashCode()返回該對象的哈希碼值,該值一般是一個由該對象的內部地址轉換而來的整數,它的實現主要是爲了提升哈希表(例如java.util.Hashtable提供的哈希表)的性能。
你能夠對它的這樣「官方式」的定義漠視,但如下這一點你必須銘記:在每一個重寫了equals方法的類中,你必須也要重寫hashCode方法。若是不這樣作的話,就會違反Object.hashCode的通用約定,從而致使該類沒法與全部基於散列值(hash)的集合類結合在一塊兒正常運行。
hashCode()的返回值和equals()的關係以下:
若是x.equals(y)返回「true」,那麼x和y的hashCode()必須相等。
若是x.equals(y)返回「false」,那麼x和y的hashCode()有可能相等,也有可能不等。
說了這麼多,他們之間的具體關係仍是看個例子好,如下是51px中吳老師的一個例子。
public class TestEquals { public static void main(String args[]) { Student s1 = new Student("張一", 6); Student s2 = new Student("張一", 6); if (s1.equals(s2)) { System.out.println("相同 s1的代碼:" + s1.hashCode() + " s2的代碼:" + s2.hashCode()); } else { System.out.println("不相同"); } } } class Student { private int age; private String name; public Student() { } public Student(String name, int age) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int hashCode() { return (this.name.hashCode() + this.age) * 31; } public boolean equals(Object obj) { boolean result = false; if (obj == null) { result = false; } if (this == obj) { result = true; } if (obj instanceof Student) { Student stu = (Student) obj; if (stu.getName().equals(this.name) && stu.getAge() == (this.age)) { result = true; } } else { result = false; } return result; } }