天天看點

java基礎----比較對象 hashcode 與 equals 與 ==

介紹

hashcode和equals是Object類中定義的方法;

hashCode 源碼:

public native int  hashCode();
           

equals()源碼:

public boolean  equals(Object obj) {
        return (this == obj);
     }
           

從equals源碼可以看到 對于Object  equals 和 == 傳回同樣的結果

而因為Object是所有類型基類 其他類型的equals與==也應傳回同樣結果

測試

測試代碼:

public static void test(Object o1,Object o2){
		boolean b=(o1==o2);
		System.out.println("a == b?"+b);
		System.out.println("equals?"+o1.equals(o2));
		System.out.println("hash相等?"+(o1.hashCode()==o2.hashCode()));
	}
           
public static void main(String[] args) throws CloneNotSupportedException {
		
		Integer i = new Integer(10);
		Integer j = new Integer(10);
		Integer k=j;
		System.out.println("1:整型的對象");
		test(i,j);
		System.out.println("2: 拷貝整型對象");
		test(j,k);
		
		System.out.println("3: 基礎類型");
		int a=1;
		int b=1;
		test(a,b);
		
		System.out.println("4: object類型");
		Object o1 = new Object();
		Object o2 = o1;
		test(o1,o2);
		
		System.out.println("5: String類型");
		String s1=new String("s");
		String s2=new String("s");
		test(s1,s2);}
           

測試結果:output 卻顯示 兩個不同的對象 隻要内容相同則equals為TRUE 并且hashcode相等 

1:整型的對象

a == b?false

equals?true

hash相等?true

2: 拷貝整型對象

a == b?true

equals?true

hash相等?true

3: 基礎類型

a == b?true

equals?true

hash相等?true

4: object類型

a == b?true

equals?true

hash相等?true

5: String類型

a == b?false

equals?true

hash相等?true

原因分析

 關于hashcode的說明  1、程式執行時對象的hashcode不變  2、如果A.equals(B) 那麼A,B的hashcode 相等 3、A.equals(B)==FALSE A,B的hashcode 不被要求一定要不等

是以基類 再重寫 equals 時 根據上面的原則也要重寫hashcode() 保證 相等對象 hashcode相等

以Integer類為例  1.對象不為空且值相等 就是相等 2. hashcode函數直接傳回int的值

public boolean  equals(Object obj) {
          if (obj instanceof Integer) {
              return value == ((Integer)obj).intValue();
          }
          return false;
      }
           
<span style="font-family: Arial, Helvetica, sans-serif;">@Override</span>
           
946     public int More ...hashCode() {
947         return Integer.hashCode(value);
948     }
           
public static int More ...hashCode(int value) {
960         return value;
961     }
           

而在String類中hashcode是這樣計算的 (沒看懂原理)

public int More ...hashCode() {
1453        int h = hash;
1454        if (h == 0 && value.length > 0) {
1455            char val[] = value;
1456
1457            for (int i = 0; i < value.length; i++) {
1458                h = 31 * h + val[i];
1459            }
1460            hash = h;
1461        }
1462        return h;
1463    }
           

總結

equals 方法要比較 對象的内容 而 “==” 比較的是對象的位址,使用自定義類 再重寫equals時 也要相應的重寫hashcode

更新:hashcode隻是hash表中的位址  hashcode相同不一定是同一對象隻說明在同一條hash鍊上(hash算法生成的值相同而已)

補充 Object.toString(); 列印了Object的hashcode

public String   toString() {
236        return getClass().getName() + "@" + Integer.toHexString(hashCode());
237    }
           

在自定義類中可以調用 super.toString() 或者 super.hashCode() 來區分對象位址 

例子:

public class ObjectTest implements Cloneable {
	/**
	 * 測試 1、toString()函數 2、hashCode() 3、finalize() 4、equals()
	 */
	public int value;
	ObjectTest(int value){
		this.value=value;
	}
	@Override
	public int hashCode(){
		return value;
	}
	public boolean equals(Object obj){
		if(obj==null)
			return false;
		if(obj.getClass()==this.getClass()){
			ObjectTest test=(ObjectTest)obj;
			if(test.value==this.value)
				return true;
			}
		return false;
	}
	public String toString(){
		String str=String.valueOf(value);
		return str;
	}
	//調用object.tostring 列印object hashcode 差別對象的位址
	public int printAddr(){
		return super.hashCode();
	}
           
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">結果:</span>
           
System.out.println("6: 自定義類型");
		ObjectTest t1=new ObjectTest(10);
		ObjectTest t2=new ObjectTest(10);
		ObjectTest t3=(ObjectTest) t1.clone();
		ObjectTest t4=t2;
		System.out.println(t3.printAddr());
		System.out.println(t4.printAddr());
		System.out.println(t2.printAddr());
		test(t1,t2);
		test(t1,t3);