第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

相關文章
相關標籤/搜索