Java覆盖hashCode()获取StackOverflowError [英] Java overriding hashCode() gets StackOverflowError
问题描述
所以我不太精通覆盖hashCode,并且似乎对hashCode方法进行了一些无限递归.
so I'm not well versed in overriding hashCode and I seem to have some infinite recursion somehow going on with the hashCode method.
这是我的情况,我有一个DuplicateCache类,它是一个缓存对象,用于检查系统中是否存在重复对象.我有一个静态内部类Duplicate,它表示Duplicate对象.
Here is my scenario, I have a class DuplicateCache that is a cache object that checks for duplicate objects in our system. I have a static inner class Duplicate which represents the Duplicate objects.
DuplicateCache维护一个HashMap来跟踪其所有条目.每个条目都包含一个Duplicate对象作为键,一个Long对象作为值.
The DuplicateCache maintains a HashMap to keep track of all its entries. Each entry consists of a Duplicate object as the key and a Long object as the value.
我正在使用Duplicate对象键执行我的所有操作,当我将put方法运行到HashMap中时,Duplicate对象的hashCode()方法将变得无限递归.
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.
重复的hashCode()方法调用了我必须重写的另一个类的hashCode,因此我将在其后加上
The hashCode() method in duplicate calls a hashCode of another class I had to override, so I'll include that after
事不宜迟,这是我对令人讨厌的Duplicate类的代码:
Without further ado, here is my code for the offending Duplicate class:
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()方法:
That does it for the Duplicate object, now the MagicPrice hashCode() method:
@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()方法会被破坏.
In this class the value field is a BigDecimal and the iso4217code is a String. 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.
有人可以向我解释一下有关hashCode()重写的内容吗?我知道一定有我在做错事才能产生这种行为.
Could someone please explain to me what I am missing about this hashCode() overriding? 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 ...>
该跟踪还引用了专有的get方法,因此可以满足您的需求:
Also that trace references a proprietary get method so heres that for you:
public Object get(Object key) {
expire();
return hashtable.get(key);
}
expire()是一种基于时间的方法,用于删除表中的旧条目 hashtable是HashMap对象
expire() is a method that does time based removal of old entries in the table hashtable is the HashMap object
谢谢!
推荐答案
对于StackOverflowError
,堆栈跟踪结束的位置(基本上是随机的,可能与问题完全无关)并不重要,但重复的是什么在此之前的顺序是-并且应该指出您的问题所在.
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.
您的hashCode()
方法看起来不错,它们应该不会导致StackOverflowError
.
Your hashCode()
methods look fine, they shouldn't be able to cause a StackOverflowError
.
这篇关于Java覆盖hashCode()获取StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!