深入理解equals和hashCode方法

  

<强>前言
  

  

在程序设计中,有很多的“公约”,遵守约定去实现你的代码,会让你避开很多坑,这些公约是前人总结出来的设计规范。

  

对象类是Java中的万类之祖,其中,equals和hashCode是2个非常重要的方法。

  

这2个方法总是被人放在一起讨论。最近在看集合框架,为了打基础,就决定把一些细枝末节清理掉。一次性搞清楚!

  

下面开始剖析。

  

<强>公共布尔=(对象obj)
  

  

对象类中默认的实现方式是:返回这个==obj。那就是说,只有这和obj引用同一个对象,才会返回真的。

  

而我们往往需要用=来判断2个对象是否等价,而非验证他们的唯一性。这样我们在实现自己的类时,就要重写=

。   

按照约定,等于要满足以下规则。

  
      <李>自反性:x.e quals (x)一定是真正的李   <李>对零:x.e quals (null)一定是假李   <李>对称性:x.e quals (y)和y.equals (x)结果一致李   <李>传递性:a和b=, b和c=,那么a和c也一定=。   <李>一致性:在某个运行时期间,2个对象的状态的改变不会不影响=的决策结果,那么,在这个运行时期间,无论调用多少次等于,都返回相同的结果。   
  

一个例子

        1类测试   2){   3私人int num;   4私人字符串数据;   5   6公共布尔=(对象obj)   7 {   8如果(这==obj)   9返回true;   10   11如果((obj==null) | | (obj.getClass () !=this.getClass ()))   12返回false;   13//能执行到这里,说明obj和这同类且非null。   obj 14测试测试=(测试);   15日返回num==test.num&和;(data=https://www.yisu.com/zixun/=测试。数据| |(数据!=null & & data.equals (test.data)));   16}   17   18公共int hashCode ()   19日{   20//重写等于,也必须重写hashCode。具体后面介绍。   24}   25   26}      

<强>=编写指导
  

  

测试类对象有2个字段,num和数据,这2个字段代表了对象的状态,他们也用在=方法中作为评判的依据。

  

在第8行,传入的比较对象的引用和这做比较,这样做是为了节省时间,节约执行时间,如果这和obj是对同一个堆对象的引用,那么,他们一定是qeuals的。

  

接着,判断obj是不是为null,如果为null,一定不等于,因为既然当前对象这能调用=方法,那么它一定不是null,非零和零当然不等价。

  

然后,比较2个对象的运行时类,是否为同一个类。不是同一个类,则不equals.getClass返回的是这和obj的运行时类的引用。如果他们属于同一个类,则返回的是同一个运行时类的引用。注意,一个类也是一个对象。

  

1,有些程序员使用下面的第二种写法替代第一种比较运行时类的写法。应该避免这样做。

        如果((obj==null) | | (obj.getClass () !=this.getClass ()))   返回错误;   如果(!(obj instanceof测试)   返回错误;//避免避免!   之前      

它违反了公约中的对称原则。

  

例如:假设狗扩展了动物类。

  

狗instanceof动物得到真正的

  

动物instanceof狗得到假

  

这就会导致

  

animal.equls(狗)返回真正的
  dog.equals(动物)返回假

  

仅当测试类没有子类的时候,这样做才能保证是正确的。

  

2,按照第一种方法实现,那么=只能比较同一个类的对象,不同类对象永远是错误的。但这并不是强制要求的。一般我们也很少需要在不同的类之间使用平等的。

  

3,在具体比较对象的字段的时候,对于基本值类型的字段,直接用==来比较(注意浮点数的比较,这是一个坑)对于引用类型的字段,你可以调用他们的平等,当然,你也需要处理字段为零的情况。对于浮点数的比较,我在看Arrays.binarySearch的源代码时,发现了如下对于浮点数的比较的技巧:

        如果(Double.doubleToLongBits (d1)==Double.doubleToLongBits (d2))//d1和d2是两类型      如果(Float.floatToIntBits (f1)==Float.floatToIntBits (f2))//f1和f2是d2是浮动类型   之前      

4,并不总是要将对象的所有字段来作为平等的评判依据,那取决于你的业务要求。比如你要做一个家电功率统计系统,如果2个家电的功率一样,那就有足够的依据认为这2个家电对象等价了,至少在你这个业务逻辑背景下是等价的,并不关心他们的价钱啊,品牌啊,大小等其他参数。

深入理解equals和hashCode方法