简体   繁体   English

Java覆盖hashCode()获取StackOverflowError

[英]Java overriding hashCode() gets StackOverflowError

so I'm not well versed in overriding hashCode and I seem to have some infinite recursion somehow going on with the hashCode method. 所以我不太精通覆盖hashCode,并且似乎对hashCode方法进行了一些无限递归。

Here is my scenario, I have a class DuplicateCache that is a cache object that checks for duplicate objects in our system. 这是我的情况,我有一个DuplicateCache类,它是一个缓存对象,用于检查系统中是否存在重复对象。 I have a static inner class Duplicate which represents the Duplicate objects. 我有一个静态内部类Duplicate,它表示Duplicate对象。

The DuplicateCache maintains a HashMap to keep track of all its entries. DuplicateCache维护一个HashMap来跟踪其所有条目。 Each entry consists of a Duplicate object as the key and a Long object as the value. 每个条目都包含一个Duplicate对象作为键,一个Long对象作为值。

I am performing all my operations using the Duplicate object keys, and when I run the put method into the HashMap, there becomes infinite recursion in the hashCode() method of the Duplicate object. 我正在使用Duplicate对象键执行所有操作,并且当我在HashMap中运行put方法时,Duplicate对象的hashCode()方法中将具有无限递归。

The hashCode() method in duplicate calls a hashCode of another class I had to override, so I'll include that after 重复的hashCode()方法调用了我必须重写的另一个类的hashCode,因此我将在之后

Without further ado, here is my code for the offending Duplicate class: 事不宜迟,这是我讨厌的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;
    }        
}

That does it for the Duplicate object, now the MagicPrice hashCode() method: 对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();
}

In this class the value field is a BigDecimal and the iso4217code is a String. 在此类中,值字段是BigDecimal,而iso4217code是字符串。 For what its worth the stackTrace finally dies in the BigDecimal hashCode() method, but I wouldn't believe the BigDecimal hashCode() method would be broken. 对于它的价值,stackTrace最终在BigDecimal hashCode()方法中死亡,但是我不相信BigDecimal hashCode()方法会被破坏。

Could someone please explain to me what I am missing about this hashCode() overriding? 有人可以向我解释一下有关hashCode()重写的内容吗? I know there must be something I'm doing wrong to generate this behaviour. 我知道一定有我在做错事情才能产生这种行为。

Here is the stack trace from my log file: 这是我的日志文件中的堆栈跟踪:

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

Also that trace references a proprietary get method so heres that for you: 该跟踪还引用了专有的get方法,因此可以为您提供以下信息:

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

expire() is a method that does time based removal of old entries in the table hashtable is the HashMap object expire()是一种方法,该方法基于时间删除表哈希表中的旧条目是HashMap对象

Thanks! 谢谢!

With a StackOverflowError , it's not important where the stack trace ends (that's basically random, and may be completely unrelated to the problem), but what the repeating sequence before that is - and that should point out exactly what your problem is. 使用StackOverflowError ,堆栈跟踪结束的位置(基本上是随机的,可能与问题完全无关)并不重要,但是在此之前的重复序列是什么-这应该指出您的问题是什么。

Your hashCode() methods look fine, they shouldn't be able to cause a StackOverflowError . 您的hashCode()方法看起来不错,它们应该不会导致StackOverflowError

Post the stack trace. 发布堆栈跟踪。 If you're getting a SO Exception then you've obviously got a referential loop in the object definitions somewhere. 如果您遇到SO异常,那么您显然在某处的对象定义中有一个引用循环。 The stack trace should make it immediately apparent where. 堆栈跟踪应该使它立即可见在哪里。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM