2つのクラスは、両方とも他のオブジェクトへの参照を含むように定義されています。彼らは(これが簡略化され、私の本当のドメインモデルクラスAは、Bのリストが含まれており、各Bは、バック親Aへの参照を持っている中で)次のようになり:Javaで循環参照を持つオブジェクトのequalsとhashCodeを実装する
public class A {
public B b;
public String bKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((b == null) ? 0 : b.hashCode());
result = prime * result + ((bKey == null) ? 0 : bKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof A))
return false;
A other = (A) obj;
if (b == null) {
if (other.b != null)
return false;
} else if (!b.equals(other.b))
return false;
if (bKey == null) {
if (other.bKey != null)
return false;
} else if (!bKey.equals(other.bKey))
return false;
return true;
}
}
public class B {
public A a;
public String aKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((aKey == null) ? 0 : aKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof B))
return false;
B other = (B) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (aKey == null) {
if (other.aKey != null)
return false;
} else if (!aKey.equals(other.aKey))
return false;
return true;
}
}
hashCode
とequals
のEclipseによって生成されましたどちらのオブジェクトでもequals
またはhashCode
メソッドを呼び出すと、他のオブジェクトのequals
およびhashCode
メソッドが呼び出されるため、StackOverflowError
という結果になるという問題があります。たとえば、次のプログラムは、上記の目的を使用してStackOverflowError
で失敗します:
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
A a1 = new A();
B b1 = new B();
a1.b = b1;
b1.a = a1;
System.out.println(a.equals(a1));
}
をその後、私に知らせてください。この方法では、円形の関係で定義されたドメインモデルを有する本質的に何か問題がある場合。限り、これはかなり一般的なシナリオですが、私が言うことができる限り、正しい?
この場合、hashCode
とequals
を定義するベストプラクティスは何ですか。私はequals
メソッドのすべてのフィールドをオブジェクトに真の深い等価比較するようにしたいが、私はこの問題をどのようにすることができないのか分かりません。ありがとう!
は、なぜあなたは、親への参照を持っている子どもたちが必要なのでしょうか?これはあなたの人生をシリアライゼーションに関して非常に複雑にするつもりです – I82Much
私は従来のドメインモデルを使っています。私のシリアライゼーションは、本質的に子供の親の関係を取り除き、逆直列化の関係を修正します。循環参照はドメインモデルで共通のものではありませんか?基礎となるDB関係は、JBossツールによって循環参照付きのJPAオブジェクトにリバースエンジニアリングされたOneToManyです。 – Tom