1、为什么要重写hashCode()和equals()?
1、hashCode的作用?
为了提高数据索引效率,Java采用了哈希表的原理,也就是哈希算法(散列算法),是将数据依特定算法直接指定道一个地址上。可以理解为hashCode方法实际上返回的就是对象存储的物理地址。但是实际上不全是,当hashCode定位到物理位置上时,这个位置上没有元素,他就被直接存储到该位置,如果有元素了,就会调用equals方法与之比较,相同了就不存,不相同就会散列其他的地址。以后会用集合做例子,来进行分析
2、equals方法的作用?
是用来比较对象是否相同,在Java中,如果两个对象相同,他们的hashCode值一定相同,但是反之,如果两个对象的hashCode相同,他们并不一定形同。
终极问题:为了提高比较程序效率,快速进行比较,需要为类的对象重写equals方法,重写equals方法,同时要重写hashCode方法
2、重写一个类的 equals 方法时就应当连同重写 hashcode 方法
一致性,即:当两个对象 equals 比较为 true,那么 hashcode 值应当相等,反之亦然,因为当两个对象hashcode 值相等,但是 equals 比较为 false,那么在 HashMap 中会产生链表,影响查询性能
3、如何编写一个完美的equals方法
1)显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量(参数名命名,强制转换请参考建议5)
2)检测otherObject是否为null ,如果为null,返回false.if(otherObject == null) return false;
-
检测this与otherObject是否引用同一个对象 :if(this == otherObject) return true;(存储地址相同,肯定是同个对象,直接返回true)
-
比较this与otherObject是否属于同一个类 (视需求而选择)
-
如果equals的语义在每个子类中有所改变,就使用getClass检测 :if(getClass()!=otherObject.getClass()) return false; (参考前面分析的第6点)
-
如果所有的子类都拥有统一的语义,就使用instanceof检测 :if(!(otherObject instanceof ClassName)) return false;(即前面我们所分析的父类car与子类bigCar混合比,我们统一了批次相同即相等)
-
将otherObject转换为相应的类类型变量:ClassName other = (ClassName) otherObject;
-
现在开始对所有需要比较的域进行比较 。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true,否则就返回flase。
-
如果在子类中重新定义equals,就要在其中包含调用super.equals(other)
-
当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明 相等对象必须具有相等的哈希码 。