覆盖equals时,遵守通用约定
对equal方法的覆盖看起来很简单,但是有许多情况是容易导致错误,最好的避免这些错误的办法
就是不覆盖equals方法.
必须遵循的原则:
自反性--对于任何非空的引用 x,有x.equals(x) 为true;
对称性--对于任何非空的引用x,y,如果x.equals(y) 为true,则必有y.equals(x) 为true;
传递性--对于任何非空的引用x,y,z,如果x.equals(y) 为true且y.equals(z) 为true,
则必有x.equals(z) 为true;
一致性--对于任何非空的引用x,y,只要equals的比较操作在对象中所用信息没被修改,
多次调用x.equals(y)会一致为TRUE或者一致为FALSE。
对于任何非空x,x.equals(null) 为FALSE。
实现高质量的equals方法的诀窍:
1、使用==操作符检查是否为这个对象的引用。
2、使用instanceof检查参数类型。
在继承类或者接口调用时候,为了防止强制转换错误,经常会先用instanceof判断类型参数
3、把参数转换成正确的类型。因为前面作了instanceof测试,所以强制转换不会错误
4、对于该类中的关键域 ,检查参数中的域与该对象中对于域是否匹配。
覆盖equals时总是要覆盖hashCode
只要对象的equals方法比较操作所用到的信息没被修改,那么对这个对象调用多次,hashCode
方法必须始终返回同一个整数。
如果两个对象根据equals方法比较是相等的,那么调用这两个对象调用hashCode必须是同一个值
如果两个对象的equals方法比较不相等,那么调用这两个对象hashCode不一定产生不同的整数。
相等的对象必须具有相等的散列码
public final class Phone{
.....
@Override
public boolean equals(Object o){
....
}
}
假设你企图将这个类与hashMap一起使用:
Map<Phnoe,String> map= new HashMap<Phnoe,String>();
map.put(new Phone(),"lily");
这时候,你可能期望map.get(new Phone())会返回一个 “lily”,但是实际返回为null
注意:这里涉及两个Phone实例,第一个被插入到map集合中,第二个实例和第一个相等,被用于获取
,由于Phone类没有覆盖hashCode方法,从而导致两个相等的实例具有不同的散列码,违反了hashCode方法
约定。即put把一个Phone放入一个散列筒,但是get从另一个散列筒中拿取,所以为null;
即便是正好从一个散列筒中操作,也会因为Hashmap‘的优化,可以缓存相关联的的散列码。这样get得到的也是null。
【代码优化】equals深入理解,布布扣,bubuko.com
【代码优化】equals深入理解
原文:http://blog.csdn.net/honjane/article/details/36401079