【代码优化】equals深入理解
覆盖equals时,遵守通用约定
对equal方法的覆盖看起来非常easy,可是有很多情况是容易导致错误,最好的避免这些错误的办法
就是不覆盖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。