2017-03-09 74 views
1

我碰到過這段代碼。我從來沒有見過以這種方式實施的平等。讓我感到震驚的是,它確實是「整潔」的,從某種意義上說,這只是一行樣板。這是否合法?

但是,我從未見過這種方法的事實讓我感到懷疑。根據Java equals和hashCode的合同,以下實現是否合法?

@Override 
public boolean equals(Object o) 
{ 
    return this == o || o instanceof DetailsPageTrackingRequest 
    && this.hashCode() == o.hashCode(); 
} 

@Override 
public int hashCode() 
{ 
    //java.util.Objects 
    return Objects.hash(pageTrackingRequest, searchId, productId); 
} 
+0

那麼,你檢查這是否是相同的實例,或者如果這是一個實例(如果它在同一場合不是null),然後比較哈希。這似乎不是一個壞主意,但我可能會錯過一些東西 – AxelH

+0

還要確保你真的想使用'instanceof'而不是'getClass()' - 參見http://stackoverflow.com/q/596462/2513200以選擇參數或另一個。當使用'instanceof'時,意外地打破對稱是非常容易的。 – Hulk

回答

1

這可能是一個壞主意,因爲其他答案中已經提到的原因。

至於「法律」方面,Contract of Object.equals狀態

的equals方法實現非空對象引用的等價關係:

  • 自反性:對於任何非空參考值x,x.equals(x)應該返回true。
  • 它是對稱的:對於任何非空引用值x和y,當且僅當y.equals(x)返回true時,x.equals(y)才返回true。
  • 它是可傳遞的:對於任何非空引用值x,y和z,如果x.equals(y)返回true並且y.equals(z)返回true,則x.equals(z)應該返回true 。
  • 它是一致的:對於任何非空引用值x和y,只要修改了對象的等值比較中沒有使用的信息,則x.equals(y)的多個調用始終返回true或始終返回false。
  • 對於任何非空引用值x,x.equals(null)應該返回false。

循序漸進:

  • 反思:是的,由於this == o
  • 對稱:由於使用的instanceof,我們需要考慮所有超和子類是確定
  • 傳遞性:取決於對稱性要求,否則是
  • 一致性:是
  • x.equals(null)應該返回false:從一個純粹的法律點instanceof

所以是的,因爲,這取決於其他實現是否進行的跨您的繼承層次結構違反了對稱性和傳遞 - 看到答案Any reason to prefer getClass() over instanceof when generating .equals()?

但是,除此之外,考慮到hashCode不需要爲非等價實例生成不同的值,通常不是定義相等的好方法。


一個例子:

甲不可變點類具有兩個字段xy

class Point { 
    final int x; 
    final int y 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

- >有2^32 * 2^32 = 2^64不同的狀態,但只有2^32可能散列碼。這意味着根據您的實施equals,有很多點將被視爲相等。


還看到有人絆倒散列碰撞與Objects.hash創造了Strings哈希這個例子equals and hashCode: Is Objects.hash method broken?

5

這是由你自己定義的標準,根據哪個類別的兩個實例被認爲是彼此相等的。

但是,你應該考慮pageTrackingRequest的不同組合,searchId & productId屬性可能導致相同的散列碼,你可能不想考慮這些不同的組合爲彼此相等。 equals要求所有3個屬性分別相等,這可能更有意義。

1

您應該單獨檢查屬性值,而不是僅檢查hashCode。有可能兩個完全不同的objects導致相同的hashCode不相等。

而且,equals不應完全依賴於hashCode,例如,如果hashCode方法被改變爲如下:

@Override 
public int hashCode() 
{ 
    return 31; 
} 

equals方法將開始返回true爲這不應該是案件的所有對象。

+0

......這對於'hashCode'來說是一個完全合法的實現(當然是非常糟糕的)。 – Hulk

0

這種方法是錯誤的。哈希碼相等性並不確定,因爲不相等的對象可能具有相同的哈希值。這是一個設計錯誤。