淺談equals和hashcode

轉自: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;
	}
}
相關文章
相關標籤/搜索