したがって、私は 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 は String です。その価値のために、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 オブジェクトです。
ありがとう!