介绍
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;
}
@Override
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();
}
结果:
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);