2 Stimmen

Java Überschreiben von hashCode() führt zu StackOverflowError

So ich bin nicht gut versiert in überschreiben HashCode und ich scheinen einige unendliche Rekursion irgendwie mit der HashCode-Methode zu gehen.

Hier ist mein Szenario, ich habe eine Klasse DuplicateCache, die ein Cache-Objekt ist, das für doppelte Objekte in unserem System überprüft. Ich habe eine statische innere Klasse Duplicate, die die doppelten Objekte darstellt.

Der DuplicateCache verwaltet eine HashMap, um alle seine Einträge zu verwalten. Jeder Eintrag besteht aus einem Duplicate-Objekt als Schlüssel und einem Long-Objekt als Wert.

Ich führe alle meine Operationen mit den Schlüsseln des Duplicate-Objekts durch, und wenn ich die Put-Methode in der HashMap ausführe, kommt es zu einer unendlichen Rekursion in der Methode hashCode() des Duplicate-Objekts.

Die HashCode()-Methode ruft einen HashCode einer anderen Klasse auf, die ich überschreiben musste, also füge ich das nach

Ohne weiteres ist hier mein Code für die beleidigende Duplicate-Klasse:

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;
    }        
}

Das war's für das Duplicate-Objekt, jetzt die Methode 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();
}

In dieser Klasse ist das Wertfeld ein BigDecimal und der iso4217-Code ein String. Was auch immer es wert ist, die stackTrace schließlich stirbt in der BigDecimal hashCode() Methode, aber ich würde nicht glauben, dass die BigDecimal hashCode() Methode gebrochen werden würde.

Könnte jemand bitte erklären Sie mir, was ich über diese hashCode() überschreiben fehlt? Ich weiß, es muss etwas sein, was ich falsch mache, um dieses Verhalten zu erzeugen.

Hier ist der Stack-Trace aus meiner Protokolldatei:

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 ...>

Auch diese Spur verweist auf eine proprietäre get-Methode, so hier, dass für Sie:

public Object get(Object key) {
expire();
return hashtable.get(key);
}

expire() ist eine Methode, die alte Einträge in der Tabelle zeitabhängig löscht hashtable ist das HashMap-Objekt

Danke!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X