[英]Overriding equals/hashCode on cross referencing classes in Java causes StackOverflowError
[英]Java overriding hashCode() gets StackOverflowError
所以我不太精通覆蓋hashCode,並且似乎對hashCode方法進行了一些無限遞歸。
這是我的情況,我有一個DuplicateCache類,它是一個緩存對象,用於檢查系統中是否存在重復對象。 我有一個靜態內部類Duplicate,它表示Duplicate對象。
DuplicateCache維護一個HashMap來跟蹤其所有條目。 每個條目都包含一個Duplicate對象作為鍵,一個Long對象作為值。
我正在使用Duplicate對象鍵執行所有操作,並且當我在HashMap中運行put方法時,Duplicate對象的hashCode()方法中將具有無限遞歸。
重復的hashCode()方法調用了我必須重寫的另一個類的hashCode,因此我將在之后
事不宜遲,這是我討厭的Duplicate類的代碼:
public static class Duplicate{
private String merchId;
private String custId;
private MagicPrice price;
private int status;
private boolean compareStatus;
// snip methods
@Override public boolean equals(Object o){
cat.debug("In the override equals method of Duplicate"); //DELETEME
if(o instanceof Duplicate)
return equals((Duplicate) o);
else
return false;
}
@Override public int hashCode() {
return merchId.hashCode() + custId.hashCode() + price.hashCode();
}
/*Equals method vital to the HashMap cache operations
How the compareStatus and status fields change this:
if both objects have true for compareStatus -> Equals will compare the statuses
otherwise -> Equals will not compare the statuses
If we only want to do an in_progress check, we need to compare status.
On the other hand success checks need to ignore the status.
*/
public boolean equals(Duplicate d){
try{
if(merchId.equals(d.merchId) && custId.equals(d.custId) && (price.compareTo(d.price)==0)){
if(this.compareStatus && d.compareStatus && this.status != d.status)
return false;
return true;
}
}catch(PriceException pe){
//Catching from MagicPrice.compareTo object method, return false
return false;
}
return false;
}
}
對Duplicate對象(現在是MagicPrice hashCode()方法)執行此操作:
@Override public boolean equals(Object o){
if(!(o instanceof MagicPrice))
return false;
MagicPrice p = (MagicPrice)o;
if(this.iso4217code.equals(p.iso4217code) && this.value.equals(p.value))
return true;
else return false;
}
@Override public int hashCode(){
return value.hashCode() + this.iso4217code.hashCode();
}
在此類中,值字段是BigDecimal,而iso4217code是字符串。 對於它的價值,stackTrace最終在BigDecimal hashCode()方法中死亡,但是我不相信BigDecimal hashCode()方法會被破壞。
有人可以向我解釋一下有關hashCode()重寫的內容嗎? 我知道一定有我在做錯事情才能產生這種行為。
這是我的日志文件中的堆棧跟蹤:
java.lang.StackOverflowError
at java.math.BigDecimal.hashCode(BigDecimal.java:2674)
at com.moremagic.util.MagicPrice.hashCode(Unknown Source)
at com.moremagic.core.DuplicateCache2$Duplicate.hashCode(Unknown Source)
at java.util.HashMap.get(HashMap.java:300)
at com.moremagic.util.ExpirableHashMap.get(Unknown Source)
at com.moremagic.core.DuplicateCache2.put(Unknown Source)
at com.moremagic.core.DuplicateCache2.put(Unknown Source)
at com.moremagic.core.DuplicateCache2.put(Unknown Source)
at com.moremagic.core.DuplicateCache2.put(Unknown Source)
<... and it continues with the put references for a looong time ...>
該跟蹤還引用了專有的get方法,因此可以為您提供以下信息:
public Object get(Object key) {
expire();
return hashtable.get(key);
}
expire()是一種方法,該方法基於時間刪除表哈希表中的舊條目是HashMap對象
謝謝!
使用StackOverflowError
,堆棧跟蹤結束的位置(基本上是隨機的,可能與問題完全無關)並不重要,但是在此之前的重復序列是什么-這應該指出您的問題是什么。
您的hashCode()
方法看起來不錯,它們應該不會導致StackOverflowError
。
發布堆棧跟蹤。 如果您遇到SO異常,那么您顯然在某處的對象定義中有一個引用循環。 堆棧跟蹤應該使它立即可見在哪里。
在大多數情況下,StackOverflowError意味着您的執行路徑具有無限遞歸。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.