Java 类的 equals 和 hashcode 方法

Java 语言规范要求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的引用对象没有发生改变,反复调用x.equals(y),应当返回相同的结果;
  • 对于任意非空引用x,x.equals(null) 都应当返回false;

  就对称性而言:

  • 如果子类能够拥有自己的相等概念, 则对称性需求将强制采用 getClass 进行检测。
  • 如果由超类决定相等的概念,那么就可以使用 imtanceof进行检测, 这样可以在不同 子类的对象之间进行相等的比较。

   编写一个完美的equals 方法的建议:

  1,显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。

  2,检测this与otherObject是否引用同一个对象:

    if(this == otherObject)return true;

    这条语句只是一个优化。实际上,这是一种经常采用的形式。因为计算这个等式要比一个一个地比较类中的域所付出的代价小的得多。

  3,检测otherObject 是否为null,如果为空,返回false。这项检测是很必要的。

   if(otherObject == null)return false;

  4,比较this与otherObject 是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测。

   if(getClass() != otherObject.getClass())return false;

      如果所有的子类都拥有统一的语义,就使用instanceof 检测;

   if(!(otherObject instanceof ClassName)) return false;

     5,将otherObject 装换为相应的类类型变量:

   ClassName other = (ClassName)otherObject;

  6,现在开始对所有需要比较的域进行比较了。使用==比较基本类型,使用equals比较对象域。如果所有的域都匹配,就返回true;否则返回false。

    return field1 == other.field1 && Object.equals(field2,other.field2) && ...;

  如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。

  提示:对于数组类型的域,可以使用静态的Arrays.equals方法检测相应的数组元素是否相等。

HashCode 方法:

  散列码(hash code)是由对象推导出的一个整型值。散列码是没有规律的。如果x和y是两个不同的对象,x.hashCode() 与 y,hashCode() 基本上不会相同)(也有例外)。

  • 由于hashCode方法定义在Object 类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址。
  • 如果重新定义equals方法,就必须重新定义hashCode 方法,以便用户可以将对象插入到散列表中。
  • hashCode 方法应该返回一个整型数值(也可以是负数),并合理的组合实例域的散列码,以便能够让各个不同的对象产生的散列码更加均匀。
  • 使用帮助类的静态方法,避免创建对象。
    • 基本数据类型使用包装类的hashCode() 方法如:Double.hashCode(x)。
    • 对象类型使用Object.hashCode(x)方法。Object.hash(Object... obj) 返回一个散列码,由提供的所有对象的散列码组合而得到。
    • String直接使用x.hashCode(),
    • 如果存在数组类型的域,那么可以使用Arrays.hashCode方法计算一个散列码,这个散列码由数组元素的散列码组成。

  注意:两个对象相等,他们的散列码必须相等。两个散列码相等,两个对象不一定相等。

posted @ 2019-12-03 18:04  Baby~She  阅读(144)  评论(0)    收藏  举报