重寫 equals 方法就必定要重寫 hashCode 方法?其實有個前提

若是問到 == 和 equals 的區別,相信不少程序員同窗都能脫口而出:一個是判斷地址,一個是判斷內容。
可是若是繼續追問:「你重寫過 equals 麼?」,「重寫 equals 方法的時候,必須重寫 hashCode 方法麼?」
你還能信心滿滿地回答上來麼?java

== 與 equals

1. ==

若是比較的是兩個基本數據類型,那麼 == 比較的是值;若是是兩個非基本數據類型的對象,那就是判斷它們的內存地址是否是相同;程序員

2. equals

  • 若是類沒有覆蓋 equals 方法,那麼 equals 等價於 == ;
  • 若是覆蓋了 equals 方法,那麼就須要根據 equals 方法的邏輯來判斷兩個對象是否相等。

讓咱們看看 String 中的 equals 方法是什麼樣的:web

public boolean equals(Object anObject{
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
複製代碼

咱們能夠看到 String 的比較,是先比較內存地址,若是兩個字符串指向的地址不同,那麼再比較兩個字符串的值。app

正確使用 equals 方法

咱們在使用 equals 方法的時候,容易發生空指針異常,因此在使用前須要判斷對象是否爲 null,或者用常量來調用 equals:this

if(string != null && string.equals("CodeDashu")){}

if("CodeDashu".equals(string)){}
複製代碼

另外你們也可使用 java.util.Objects 中的 equals 方法:spa

Objects.equals(string"CodeDashu");
複製代碼

從這個方法的源碼中能夠看出,方法已經幫咱們考慮到控制值的問題了,因此能夠放心使用。指針

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

複製代碼

覆蓋 equals 方法的準則

  • 自反性:對於任何非空引用值 A,A.equals(A) 返回 true。
  • 對稱性:對於任何非空引用值 A 和 B,A.equals(B) 和 B.equals(A) 的結果相同。
  • 傳遞性:對於任何非空引用值 A、B 和 C,若是 A.equals(B) 返回 true, A.equals(C) 返回 true,那麼 - B.equals(C) 也是 true。
  • 一致性:對於任何非空引用值 A 和 B,每一次調用 x.equals(y) 的結果是相同的。
  • 非空性:對於任何非空引用值 A,A.equals(null) 應返回 false。

equals() 與 hashCode()

hashCode() 方法是獲取 hash 碼(哈希碼、散列碼),咱們能夠把它看作返回一個 int 整數;hash 碼的做用是肯定對象在散列結構中的位置。
hashCode() 方法存在於 Object 類中,表明 Java 中的任何類都會有 hashCode() 方法,那麼任何場景下 hashCode() 都會產生做用麼?其實並非!code

若是對象會被放入散列結構中使用,那麼 hashCode() 就會起做用。
好比,當咱們要向 HashMap 中放入一組 key-value 的時候,那麼 HashMap 會先根據 key 對象的 hashCode 值判斷存入的位置,若是 key 存入的位置上已經有了一個元素,再根據 equals() 方法判斷兩個元素是否相等;若是確認相等,那麼會覆蓋原來的 key-value 。orm

final V putVal(...){
   ...

   if (p.hash == hash &&
              ((k = p.key) == key || (key != null && key.equals(k))))
              e = p;
   ...
}
複製代碼

這時候,equals() 與 hashCode() 就是有關係的:cdn

  • 兩個對象 equals() 返回 true 的時候,那它們的 hashCode() 值須要相等;
  • 若是兩個對象的 hashCode() 值相等,那它們 equals() 不必定是 true;(哈希衝突)
  • 因此在這種狀況下,若是要判斷兩個對象是否相等,除了要覆蓋 equals() ,也要覆蓋 hashCode(),不然就會發生意料以外的問題。

固然,若是對象不會放入散列表中使用,那麼 equals() 與 hashCode() 其實也沒啥關係。

會點代碼的大叔 | 文【原創】


@會點代碼的大叔
@會點代碼的大叔
相關文章
相關標籤/搜索