簡體   English   中英

Java覆蓋hashCode()獲取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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM