官术网_书友最值得收藏!

陷阱21 一字之差——重寫對象的hashCode方法,但重寫equals方法時參數不是Object類型

在進行程序開發時重寫了equals方法,但是沒有重寫hashCode方法,會導致程序在某些情況下出錯,同樣,如果重寫了對象的hashCode方法,但是沒有重寫equals方法或重寫equals方法時參數不是Object類型,程序在某些情況下也一樣會出現錯誤。

注意

Object類的equals方法其參數必須是Object類型的,如果其直接子類或間接子類重寫該方法,一定要保證其參數也是Object類型,否則在進行一些特殊處理(如判斷HashMap集合中是否包含某個對象)時,程序就會出現錯誤,再有就是在比較兩個對象時,也一定要重寫equals方法,否則程序一樣會出錯。

下面看一個重寫對象的hashCode方法,但是沒有重寫equals方法,導致程序出錯的實例。

例3.21.1 創建類,在該類中重寫對象的hashCode方法,但不重寫equals方法,然后創建該類的兩個實例,將其中一個實例放到HashSet集合中,并判斷該集合中是否包含另一個對象,最后再通過對象的equals 方法比較兩個對象是否相同。(光盤位置:光盤\MR\Instance\3\21\ RewriteHashCodeApp)

    import java. util. HashSet;
    import java. util. Set;
    public class Book {
      private String bookType;                    // 圖書類型
      private String bookName;                    // 圖書名稱
      public Book (String bookType, String bookName) {
          this. bookType = bookType;               // 初始化圖書類型
          this. bookName = bookName;               // 初始化圖書名稱
      }
      // 重寫hashCode方法
    public int hashCode () {
          final int prime = 31;                   // 用于計算散列碼的基數
          int result = 1;                         // 存放散列碼值的變量
          // 通過圖書類型和圖書名稱計算散列碼的值
          result = prime * result
                + ((bookName == null) ? 0 : bookName. hashCode ());
          result = prime * result
                + ((bookType == null) ? 0 : bookType. hashCode ());
          return result;                          // 返回散列碼的值
      }
      public static void main (String[] args) {
          Book book1 = new Book ("IT", "Java");    // 創建Book的實例book1
          Book book2 = new Book ("IT", "Java");    // 創建Book的實例book2
          // 輸出兩個對象的散列碼
          System.out. println ("對象book1的散列碼是:" + book1. hashCode ());
          System.out. println ("對象book2的散列碼是:" + book2. hashCode ());
          // 使用HashSet類創建Set集合對象
    Set<Book> set = new HashSet<Book>();
          set. add (book1);                         // 將Book的實例book1添加到集合
          // 查看集合中是否包含Book的實例book2
    boolean bool = set. contains (book2);
          System.out. println ("Set集合中是否包含對象book2? " + bool);
          System.out. println ("比較對象book1與book2是否相同?"+
    book1. equals (book2));
      }
    }

運行本實例,將在控制臺輸出如圖3.21所示的信息。

圖3.21 重寫hashCode方法而沒重寫equals方法

說明

從圖3.21的輸出結果可以看出,由于重寫了對象的hashCode方法,所以前兩行輸出對象book1和book2的散列碼相同,都是71349994,第3行輸出false,表示Set集合中不包含對象book2,這是由于在重寫hashCode方法的同時,沒有重寫equals方法,所以導致這樣的結果,最后一行也輸出了false,說明兩個對象book1與book2是不相同的,這也是由于在重寫hashCode方法的同時沒有重寫equals方法所導致的。

下面再看一個重寫對象的hashCode方法,同時也重寫了equals方法,但是重寫equals方法的參數不是Object類型導致程序出錯的實例。

例3.21.2 創建類,在該類中重寫對象的hashCode方法,同時也重寫了equals方法,但是重寫equals方法的參數不是Object類型而是Book類型,然后創建該類的兩個實例,將其中一個實例放到HashSet集合中,并判斷該集合中是否包含另一個對象,最后再通過這個equals 方 法 比 較 兩 個 對 象 是 否 相 同。(光 盤 位 置:光 盤 \MR\Instance\3\21\EqualsParameterErrorApp)

運行本實例,將在控制臺輸出如圖3.22所示的信息。

圖3.22 重寫equals方法,但參數不是Object類型

說明

從圖3.22的輸出結果可以看出,由于重寫了對象的hashCode方法,所以前兩行輸出對象book1和book2的散列碼相同,都是71349994,第3行輸出false,表示Set集合中不包含對象book2,這是由于在重寫equals方法時,其參數不是Object類型,實際上該方法在這里是重載了對象的equals方法,而不是重寫對象的equals方法,所以導致這樣的錯誤結果,最后一行輸出了true,說明兩個對象book1與book2是相同的,這是由于該類重載的equals方法,其參數是Book類型,因此可以對Book類的實例進行比較。

下面再看一個重寫對象的hashCode方法,同時也正確地重寫了對象的equals方法,使用程序能夠輸出正確結果的實例。

例3.21.3 創建類,在該類中重寫了對象的hashCode方法和equals方法,然后創建該類的兩個實例,將其中一個實例放到HashSet集合中,并判斷該集合中是否包含另一個對象,最后再通過equals 方法比較兩個對象是否相同。(光盤位置:光盤\MR\Instance\3\21\RightEqualsMethodApp)

運行本實例,將在控制臺輸出如圖3.23所示的信息。

圖3.23 正確重寫對象的方法輸出的結果

說明

本實例之所以輸出了正確的結果,是由于程序正確地重寫了對象的hashCode 方法和equals方法,所以輸出結果的最后兩行都輸出了true,這樣達到了程序預期的要求。

編程準則:一定要同時重寫對象的equals和hashCode方法

無論在什么情況下,如果需要重寫對象的equals方法和hashCode方法,一定要同時重寫這兩個方法,不能只重寫其中的一個方法,并且在重寫對象的equals方法時,一定要注意該方法的形參類型必須要是Object類型的,而不能是其他類型。

主站蜘蛛池模板: 叙永县| 通州市| 墨脱县| 永康市| 岐山县| 吐鲁番市| 莎车县| 杂多县| 霍城县| 炎陵县| 兴国县| 四子王旗| 竹北市| 武威市| 沈丘县| 泾川县| 富阳市| 万山特区| 滁州市| 普格县| 灵丘县| 徐州市| 盱眙县| 灌南县| 扎鲁特旗| 铜川市| 嘉义市| 镇康县| 乐亭县| 崇明县| 买车| 观塘区| 金阳县| 苏尼特左旗| 罗甸县| 桐柏县| 迭部县| 慈利县| 敦化市| 铁岭县| 金昌市|