第9条 覆盖equals时总要覆盖hashCode

你们在使用equals方法时,一个常见的错误根源就是重写了equals方法,而没有覆盖hashCode方法。java

在每一个覆盖equals方法的类中,也必须覆盖hashCode方法。若是不覆盖的话,就会违反Object.hashCode的通用约定,从而致使该类没法正常工做。ide

下面看个实例:this

public final class PhoneNumber {
   private final short areaCode;
   private final short prefix;
   private final short lineNumber;

   public PhoneNumber(int areaCode, int prefix, int lineNumber) {
      rangeCheck(areaCode, 999, "area code");
      rangeCheck(prefix, 999, "prefix");
      rangeCheck(lineNumber, 9999, "line number");
      this.areaCode = (short) areaCode;
      this.prefix = (short) prefix;
      this.lineNumber = (short) lineNumber;
   }

   private static void rangeCheck(int arg, int max, String name) {
      if (arg < 0 || arg > max)
         throw new IllegalArgumentException(name + ": " + arg);
   }

   @Override
   public boolean equals(Object o) {
      if (o == this)
         return true;
      if (!(o instanceof PhoneNumber))
         return false;
      PhoneNumber pn = (PhoneNumber) o;
      return pn.lineNumber == lineNumber && pn.prefix == prefix
            && pn.areaCode == areaCode;
   }
   
   public static void main(String[] args) {
      Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
      m.put(new PhoneNumber(707, 867, 5309), "Jenny");
      System.out.println(m.get(new PhoneNumber(707, 867, 5309)));
   }

这时候,可能也有不少人认为输出"Jenny",但它实际却返回null。因为没有覆盖hashCode方法,从而致使两个相等的实例具备不相等的散列码,违反了hashCode的约定。spa

修正这个问题也很简单,只须要为该类提供想对应的hashCode方法便可。code

因此,在每一个覆盖equals方法的类中,也必须覆盖hashCode方法。get

相关文章
相关标签/搜索