[英]Why are this == other and and this.hashcode == other.hashcode() giving different results?
我有一個帶有以下equals()
和hashCode()
方法的類
@Override
public boolean equals(Object o)
{
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Phrases that = (Phrases) o;
if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test
if (exitMsg != null ? !exitMsg.equals(that.exitMsg) : that.exitMsg != null)
{ return false; }
if (introMsg != null ? !introMsg.equals(that.introMsg) : that.introMsg != null)
{ return false; }
if (msg != null ? !msg.equals(that.msg) : that.msg != null)
{ return false; }
if (phrase != null ? !phrase.equals(that.phrase) : that.phrase != null)
{ return false; }
if (title != null ? !title.equals(that.title) : that.title != null)
{ return false; }
return true;
}
@Override
public int hashCode()
{
int result = phrase != null ? phrase.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (introMsg != null ? introMsg.hashCode() : 0);
result = 31 * result + (msg != null ? msg.hashCode() : 0);
result = 31 * result + (exitMsg != null ? exitMsg.hashCode() : 0);
return result;
}
我試圖弄清楚為什么三葉草不能說我的哈希碼方法已經運行了。 我添加了一行:
if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test
根據三葉草,每次此equals方法都運行if (this == o) { return true; }
if (this == o) { return true; }
為假,但if (this.hashCode() == o.hashCode()) { return true; }
if (this.hashCode() == o.hashCode()) { return true; }
是正確的 。
題:
為什么this == o
和this.hashCode() == o.hashCode()
不能以相同的結果求值?
根據定義,哈希碼包含的信息少於源數據。 這意味着可能發生沖突,在這種情況下,您將擁有兩個具有相同哈希碼但不相等的對象。
Java hashCode()
的一般要求是相反的:
equals
關系成立的兩個對象必須產生相同的哈希碼(反之則不成立) 基本上,關鍵是您不能將哈希碼用作唯一標識符 (實際上,JDK數據結構在內部管理沖突)。
這與==
無關,因為它只比較對象的引用(內存地址),對於它們的hashCode()
和equals幾乎相同。
如果查看一下hashCode()
您會發現,如果除了一個字段之外的所有字段都為空,但哪個字段不同,則所計算的哈希碼是相同的,這清楚地證明了您可以輕松生成沖突的事實。
如果您想要更強大的功能,則應考慮使用MessageDigest
,它產生的摘要要比int
長得多(因此,能夠容納更多信息=發生碰撞的可能性較小)。 但是即使有了它們,您也無法保證。
==
不調用.equals
。
實際上,兩者是完全不同的,僅在未覆蓋Object的默認(不良)實現的對象中重疊。
==
只是檢查太對象是否是等效的指針。
.equals
運行與您顯示的方法類似的方法。
用.equals
替換==
應該可以解決您的問題
退后一步...
考慮equals()
和hashCode()
的協定。 考慮一下契約僅是一種方式的事實:如果您同時在一個類中實現這兩種協議,那么要求是,如果一個類的兩個實例相等,則它們必須具有相同的哈希碼。
它沒有說的是,如果兩個實例具有相同的哈希碼,則它們必須相等。 但是,您假設在您的.equals()實現中!
但是在您的代碼中,有:
// WRONG!
if (this.hashCode() == o.hashCode()) { return true; }
這是一個完全有效的hashCode()
方法的示例:
public int hashCode()
{
return 42;
}
現在,我相信您可以通過.equals()方法查看問題所在。
假設使用Java 7,這是編寫兩種方法的方式。 因為兩者都考慮了null
,所以這很容易(另一方面,應盡可能避免使用null
;最終, null
只是麻煩而已):
@Override
public final int hashCode()
{
return Objects.hash(phrase, title, introMsg, msg, errorMsg);
}
@Override
public final boolean equals(final Object obj)
{
if (obj == null)
return false;
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
final MyClass other = (MyClass) obj;
return Objects.equals(phrase, other.phrase)
&& Objects.equals(title, other.title)
&& Objects.equals(introMsg, other.introMsg)
&& Objects.equals(msg, other.msg)
&& Objects.equals(errorMsg, other.errorMsg);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.