成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

equals() ? ==? hashCode()? 今天就把你們都認識清楚

開發 后端
當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址, 對象是放在堆中的,棧中存放的是對象的引用(地址)。由此可見'=='在比較的對象是引用類型時,是對棧中的地址值進行比較的。

[[393185]]

本文轉載自微信公眾號「java寶典」,作者iTengy。轉載本文請聯系java寶典公眾號。 u  

目錄

  • Java中的數據類型
  • 什么時候用關系操作符==,什么時候用equals方法?
  • equals方法,為什么報了 空指針 java.lang.NullPointerException?
  • hashCode 方法有什么作用?hashCode 和 equals 的關系?
  • 為什么每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法?

數據類型

java中的數據類型,可分為兩類:

1.基本數據類型(原始數據類型)

byte,short,char,int,long,float,double,boolean 他們之間的比較,應用雙等號(==),基礎數據類型比較的是他們的值。

2.引用類型(類、接口、數組)

當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址, 對象是放在堆中的,棧中存放的是對象的引用(地址)。由此可見'=='在比較的對象是引用類型時,是對棧中的地址值進行比較的。

關系操作符 ==

java中包含的關系操作符有小于(<)、大于(>)、小于或等于(<=)、大于或等于(>=)、等于(==)以及不等于(!=)。

==和!=適用所有對象,但是這兩個操作符通常在比較對象的時候會出問題:

在這里==和!=比較的是對象的引用。盡管對象的內容相同,但是對象的引用卻是不同的,說以n1==n2是false。

  1. Integer n1 = new Integer(47); 
  2.         Integer n2 = new Integer(47); 
  3.          
  4.         System.out.println(n1 == n2);  //false 
  5.         System.out.println(n1 != n2);  //true 

在這里 == 比較的是基本數據類型, 那么他會比較數值是否相等.所以此時 n1 == n2輸出 true.

  1. int n1 = 100; 
  2.        int n2 = 100; 
  3.  
  4.        System.out.println(n1 == n2);  //true 
  5.        System.out.println(n1 != n2);  //false 

equals方法

默認情況,對象的equals方法 調用的是Object類中equals方法.源碼如下:

  1. public boolean equals(Object obj) { 
  2.         return (this == obj);   
  3.     } 

注意這里相當于還是用的==,在這里比較的是引用對象,所以是比較地址(是不是同一個對象)

第二種情況,重寫了對象的equals方法. 例如String對象.源碼如下:

  1. public boolean equals(Object anObject) { 
  2.         if (this == anObject) { 
  3.             return true;//如果是同一個對象直接返回 
  4.         } 
  5.         if (anObject instanceof String) {//是String對象開始判斷內容. 
  6.             String anotherString = (String)anObject; 
  7.             int n = value.length; 
  8.             if (n == anotherString.value.length) { 
  9.                 char v1[] = value; 
  10.                 char v2[] = anotherString.value; 
  11.                 int i = 0; 
  12.                 while (n-- != 0) {//逐個字符比較,若有不相等字符,返回false 
  13.                     if (v1[i] != v2[i]) 
  14.                         return false
  15.                     i++; 
  16.                 } 
  17.                 return true
  18.             } 
  19.         } 
  20.         return false
  21.     } 

此時,equals方法的重寫實現不盡相同,但是重寫后一般都是通過對象的內容是否相等 來判斷 對象是否相等,對于大多數Java類庫都實現了equals()方法,以便用來比較對象的內容,而非比較對象的引用

避免equals方法,報空指針

避免equals方法報空指針,先告訴大家,答案是使用Objects.equals(a,b),在JDK7添加了一個Objects工具類,它提供了一些方法來操作對象,它由一些靜態的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的),用于計算對象的hashcode、返回對象的字符串表示形式、比較兩個對象。

在默認情況下,對象的equals方法沒有重寫 調用的是Object類中equals方法

那么我們來寫個報錯的例子:

  1. A a = null;//假設我接收到config對象,我并不知道是否為空,就進行比較 
  2.         boolean r = a.equals(new B()); 
  3.         System.out.println(r); //輸出 java.lang.NullPointerException 

此時由于我們的疏忽,接收到參數后,并沒有對參數進行校驗,導致調用equals方法報出空指針.

  1. //其它的例子有: 
  2. null.equals("java寶典");  //NullPointerException 
  3.  
  4. "java寶典".equals(null);  //false 只有equals左邊的對象不為Null時,才有結果 
  5.  
  6. null.equals(null);  //NullPointerException 

使用Objects.equals(a,b),左右 兩邊都為Null也不會報空指針

  1. Objects.equals(null,"java寶典");  //false 
  2.  
  3. Objects.equals("java寶典",null);  //false 
  4.  
  5. Objects.equals(null,null);  //true 

看一下Objects.equals方法的源碼,它是容忍空指針的

  1. public static boolean equals(Object a, Object b) { 
  2.        return (a == b) || (a != null && a.equals(b)); 
  3.    } 

hashCode() 方法

哈希(Hash)實際上是 人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也稱為散列算法,是指將數據依特定算法直接指定到一個地址上,通俗理解就是一種從任何一種數據中創建小的數字“指紋”的方法。

在java中,默認情況下,對象沒有重寫hashCode()方法.使用的是Object類中的.

  1. public native int hashCode(); //它是一個native方法. 

Object 類定義的 hashCode 方法會針對不同的對象返回不同的整數。(這是通過將該對象的內部地址轉換成一個整數來實現的)

例子:

  1. Config config1 = new Config(); 
  2.        Config config2 = new Config(); 
  3.  
  4.        System.out.println(config1.hashCode());  //1128032093 
  5.  
  6.        System.out.println(config2.hashCode());  //1066516207 
  7.  
  8.        System.out.println(config1.equals(config2));  //false 

hashCode 和 equals 的關系

二者均是Object類里的方法,由于Object類是所有類的基類,所以一切類里都可以重寫這兩個方法。

  • 原則 1 :如果 x.equals(y) 返回 “true”,那么 x 和 y 的 hashCode() 必須相等 ;
  • 原則 2 :如果 x.equals(y) 返回 “false”,那么 x 和 y 的 hashCode() 有可能相等,也有可能不等 ;
  • 原則 3 :如果 x 和 y 的 hashCode() 不相等,那么 x.equals(y) 一定返回 “false” ;
  • 原則 4 :一般來講,equals 這個方法是給用戶調用的,而 hashcode 方法一般用戶不會去調用 ;
  • 原則 5 :當一個對象類型作為集合對象的元素時,那么這個對象應該擁有自己的equals()和hashCode()設計,而且要遵守前面所說的幾個原則。

在 Java 應用程序執行期間,在對同一對象多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另一次執行,該整數無需保持一致。

如果根據 equals(Object) 方法,兩個對象是相等的,那么對這兩個對象中的每個對象調用 hashCode 方法都必須生成相同的整數結果。

如果根據 equals(java.lang.Object) 方法,兩個對象不相等,那么對這兩個對象中的任一對象上調用 hashCode 方法 不要求 一定生成不同的整數結果。但是,程序員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。

為什么每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法?

在每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法。如果不這樣做的話,就會違反Object.hashCode的通用約定,從而導致該類無法結合所有基于散列的集合一起正常運作

上面我們介紹了hashCode是什么,進一步了解 hashCode 的應用,我們必須先要了解Java中的容器,因為 HashCode 只是在需要用到哈希算法的數據結構中才有用,比如 HashSet, HashMap ..

我們以hashMap為例:

HashMap是由數組和鏈表組成的存儲數據的結構。確定一個數據存儲在數組中的哪個位置 就是通過hashCode方法進行計算出存儲在哪個位置, 產生沖突的話就會調用equals方法進行比對, 如果不同,那么就將其加入鏈表尾部,如果相同就替換原數據。計算位置當然不是上面簡單的一個hashCode方法就計算出來,中間還有一些其他的步驟,這里可以簡單的認為是hashCode確定了位置,代碼如下:

  1. public V put(K key, V value) { 
  2.      // 如果哈希表沒有初始化就進行初始化 
  3.      if (table == EMPTY_TABLE) { 
  4.          // 初始化哈希表 
  5.          inflateTable(threshold); 
  6.      } 
  7.    
  8.      // 當keynull時,調用putForNullKey方法,保存nulltable的第一個位置中,這是HashMap允許為null的原因 
  9.      if (key == null) { 
  10.          return putForNullKey(value); 
  11.      } 
  12.    
  13.      // 計算key的hash值 
  14.      int hash = hash(key); 
  15.      // 根據key的hash值和數組的長度定位到entry數組的指定槽位 
  16.      int i = indexFor(hash, table.length); 
  17.      // 獲取存放位置上的entry,如果該entry不為空,則遍歷該entry所在的鏈表 
  18.      for (Entry<K, V> e = table[i]; e != null; e = e.next) { 
  19.          Object k; 
  20.          // 通過key的hashCode和equals方法判斷,key是否存在, 如果存在則用新的value取代舊的value,并返回舊的value 
  21.          if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 
  22.              V oldValue = e.value; 
  23.              e.value = value; 
  24.              e.recordAccess(this); 
  25.              return oldValue; 
  26.          } 
  27.      } 
  28.    
  29.      // 修改次數增加1 
  30.      modCount++; 
  31.      // 如果找不到鏈表 或者 遍歷完鏈表后,發現key不存在,則創建一個新的Entry,并添加到HashMap中 
  32.      addEntry(hash, key, value, i); 
  33.      return null
  34.  }  

在上面的方法中,調用了一個方法可以看到,數組的下標是根據傳入的元素hashCode方法的返回值再和特定的值異或決定的:

  1. static int indexFor(int h, int length) { 
  2.         // 對hash值和length-1進行與運算來計算索引 
  3.         return h & (length - 1); 
  4.     } 

再回到我們的問題:為什么每個覆蓋了equals方法的類中,也必須覆蓋hashCode方法?

如果你重寫了equals, 而hashCode的實現不重寫,那么類的hashcode方法就是Object默認的hashcode方法,由于默認的hashcode方法是根據對象的內存地址經哈希算法得來的一個值,那么很可能某兩個對象明明是“相等”,而hashCode卻不一樣。

這樣,當你用其中的一個作為鍵保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一個作為鍵值去查找他們的時候 ,則根本找不到。導致HashSet、HashMap不能正常的運作.

比如:有個A類重寫了equals方法,但是沒有重寫hashCode方法,對象a1和對象a2使用equals方法相等,按照上面的hashcode的用法,那么他們兩個的hashcode肯定相等,但是這里由于沒重寫hashcode方法,他們兩個hashcode并不一樣,所以,我們在重寫了equals方法后,盡量也重寫了hashcode方法,通過一定的算法,使他們在equals相等時,也會有相同的hashcode值。

總結

== 在比較基本數據類型時,比較的是值

== 在比較引用數據類型時,比較的是對象的引用地址

對象的equals方法,在不重寫的情況下,使用的是==,比較的是對象的引用地址

對象的equals方法,在重寫以后,用于比較對象的內容是否相等,實現可以使用IDE生成或者自定義實現.(例如,String類對equals方法的重寫就是逐個比較字符)

不重寫的情況下,對象的equals方法 調用的是Object類中equals方法,在條件左邊為Null時會報空指針,使用Objects.equals(a,b)可以避免空指針

hashcode是系統用來快速檢索對象而使用的

 

重寫了equals方法后,也要重寫了hashcode方法,否則會導致HashSet、HashMap等依賴hashCode的容器不能正常的運作

 

責任編輯:武曉燕 來源: java寶典
相關推薦

2014-08-22 13:27:59

物聯網

2023-07-10 08:59:37

Dubbo通信模式

2023-04-07 00:05:30

WebGPUAPIJavaScript

2021-03-18 23:38:26

EqualsHashcode方法

2010-05-27 21:51:11

光纖接入FTTx

2020-06-04 13:15:14

equalshashCodeJava

2019-08-16 10:10:07

hashcodeequalsJava

2021-12-03 06:59:23

HashCodeEquals面試

2020-01-29 19:24:59

SQL數據庫MySQL

2019-10-23 08:45:34

SQL數據庫開發

2021-09-13 13:05:05

Redis數據庫內存

2023-02-27 23:45:09

MySQL索引存儲

2023-08-04 08:25:03

客戶配置Spring

2021-07-30 09:32:55

JavaEquals

2021-12-13 09:10:48

equalshashCodeJava

2025-04-07 08:50:36

2023-09-14 23:14:57

MySQL索引

2018-10-08 10:18:13

2023-10-08 07:13:19

equalshashCode哈希表

2020-08-06 11:05:30

函數調用寄存器語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级欧美一级日韩片 | 精品无码久久久久久国产 | 一区二区三区免费 | 一区二区三区四区在线视频 | 热re99久久精品国99热观看 | 91精品国产91| 黄色一级视频 | 欧美日韩国产一区二区三区 | 久久精品国产99国产精品 | 欧美国产日韩在线观看 | 亚洲日韩视频 | 久久99一区二区 | 久久久久久久久淑女av国产精品 | 黄色在线免费观看 | 欧美另类视频在线 | 国产欧美日韩一区二区三区 | 999久久久免费精品国产 | 国产资源一区二区三区 | 中文字幕亚洲精品 | 日本不卡在线视频 | 成人精品国产一区二区4080 | 欧美日韩国产三级 | 国产精品自拍av | 日韩av福利在线观看 | 羞羞视频在线观看 | 久久精品国产a三级三级三级 | 色综合国产 | 亚洲国产精品一区二区久久 | 精品免费在线 | 久久影音先锋 | 日韩字幕 | 亚洲成人一区二区三区 | 成人在线免费观看 | 中文字幕日韩欧美 | 亚洲国产精品成人无久久精品 | 免费毛片www com cn | 精品视频一区二区三区在线观看 | 国产精品一区二区不卡 | 精品国产乱码久久久久久丨区2区 | 午夜欧美 | 国产一区二区三区久久久久久久久 |