不重写hashCode的时候,返回的通常是对象的内存地址,JDK文档原文是"typically implemented by converting the internal address of the object into an integer"。另外,文档说,重写equals,就必须重写hashCode,因为hashCode规定,如果a.equals(b)==true,则必有a.hashCode()==b.hashCode()。原文是 " so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes." 不重写equals的时候,比较的是引用(Reference),也就是内存地址,见JDK的源码: public boolean equals(Object obj) { return (this == obj); } 这个实现是符合上面的规定的。如果重写了equals,就有可能打破了上面的规定。这是因为,你自己定义的equals有可能让地址不同(也就是hashCode不同)的两个对象相等。所以要将hashCode一并重写。注意,这个关系是单向的,java并不要求hashCode相同的对象一定要相互equal。
在都不重写的时候
equals比较的是对象的内存地址
hashcode打印的也是对象的内存地址
所有看起来equals比较靠的是hashcode
其实可以不一样
2、集合里面元素,重写equals()的时候要重写hashcode(),如hashset、treeset、hashmap等;
下面这个这个比较严谨:
如果该对象没有重写object的equals方法,equals比较的是对象的hashcode。
/**
*一般equals的效率能更高一些,比如
*hashcode就是简单的理解就是计算对象的权值(就是一种特殊值,只有内容相等的才会一样)
*而就是是在必须进行hashcode的时候才会去调用hashcode
*
*/
//比如这是一个hashcode算法,计算比较复杂吧
hashcode(){ return ((n*(n-1)+ n - (n - 1) ) + (n - 2) ..... - 1)}equals (Object obj){
//判断引用是否相等,如果等就直接返回,不用计算hashcode的值
if( this == obj)
{
return true;
}
else{
if(obj instanceof this.getClass().getName())
{
//这里才真正计算hashcode ,所以效率比较高
if(this.hashcode() == obj.hashcode())
{
return ture;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
个人看法,仅供参考
例如,使用 class { String a; int b} 的实例作为Key,K={a="hi", b=2}的对象的hashcode假设是 1000,然后用它做key, hashmap.put( K, "something");后,把改对象的成员 a 改为 其他值,例如 K.a="hello", 然后再用它做key,调用 hashmap.get(K), 你就会发现,即使是实际内容已经变了,但是还是返回“somnthing”。
equals相等,hashCode一定相等。
" so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes." 不重写equals的时候,比较的是引用(Reference),也就是内存地址,见JDK的源码:
public boolean equals(Object obj) {
return (this == obj);
}
这个实现是符合上面的规定的。如果重写了equals,就有可能打破了上面的规定。这是因为,你自己定义的equals有可能让地址不同(也就是hashCode不同)的两个对象相等。所以要将hashCode一并重写。注意,这个关系是单向的,java并不要求hashCode相同的对象一定要相互equal。