2

所以我并不精通覆盖 hashCode 并且我似乎在 hashCode 方法上有一些无限递归。

这是我的场景,我有一个 DuplicateCache 类,它是一个缓存对象,用于检查我们系统中的重复对象。我有一个静态内部类 Duplicate,它代表 Duplicate 对象。

DuplicateCache 维护一个 HashMap 来跟踪它的所有条目。每个条目都包含一个作为键的 Duplicate 对象和一个作为值的 Long 对象。

我正在使用 Duplicate 对象键执行所有操作,当我将 put 方法运行到 HashMap 中时,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() 是一种基于时间删除表中旧条目的方法 hashtable 是 HashMap 对象

谢谢!

4

3 回答 3

5

使用 a StackOverflowError,堆栈跟踪结束的位置并不重要(这基本上是随机的,并且可能与问题完全无关),但在那之前的重复序列是什么 - 这应该准确地指出你的问题是什么。

您的hashCode()方法看起来不错,它们不应该导致StackOverflowError.

于 2010-01-15T19:32:18.043 回答
0

发布堆栈跟踪。如果你得到一个 SO Exception,那么你显然在对象定义的某个地方有一个引用循环。堆栈跟踪应该立即显示在哪里。

于 2010-01-15T19:25:07.480 回答
0

在大多数情况下,StackOverflowError 意味着您在执行路径中有无限递归。

于 2010-01-16T02:13:32.997 回答