首页 > 代码库 > 【代码优化】equals深入理解

【代码优化】equals深入理解

覆盖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。