Tengo dos clases definidas de manera que ambas contienen referencias al otro objeto. Ellos similar a esto (esto es simplificada, en mi dominio real de la clase del modelo A contiene una lista de B y cada B tiene una referencia de nuevo a los padres A):Implementando equals y hashCode para objetos con referencias circulares en Java
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;
}
}
El hashCode
y equals
se han generado por Eclipse usando ambos campos de A y B. El problema es que llamar al método equals
o hashCode
en cualquier objeto da como resultado un StackOverflowError
ya que ambos llaman al otro objeto equals
y hashCode
método. Por ejemplo, el siguiente programa fallará con StackOverflowError
usando los objetos anteriores:
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));
}
Si hay algo intrínsecamente malo en tener un modelo de dominio definido con las relaciones circulares de esta manera, por favor hágamelo saber. Por lo que puedo decir, aunque este es un escenario bastante común, ¿correcto?
¿Cuál es la mejor práctica para definir hashCode
y equals
en este caso? Quiero mantener todos los campos en el método equals
para que sea una verdadera comparación de igualdad profunda en el objeto, pero no veo cómo puedo hacerlo con este problema. ¡Gracias!
¿Por qué necesitan los niños a tener referencias a los padres? Esto va a complicarle la vida con respecto a la serialización – I82Much
Estoy trabajando con un modelo de dominio heredado. Mi serialización deja esencialmente fuera la relación de los padres en el niño y luego corrige la relación en la deserialización. ¿Tener referencias circulares no es algo común en los modelos de dominio? La relación de base de datos subyacente es OneToMany que se diseñó mediante ingeniería inversa mediante herramientas JBoss en objetos JPA CON las referencias circulares. – Tom