У меня есть два класса, определенные так, что они оба содержат ссылки на другой объект. Они похожи на это (это упрощенная, в мой реальный домен модель класса А содержит список B, а каждый имеет обратную ссылку на родительскую A):Реализация equals и hashCode для объектов с круговыми ссылками в 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;
}
}
hashCode
и equals
были сгенерированы Затмении используя оба поля как A, так и B. Проблема заключается в том, что вызов метода на любом из объектов приводит к StackOverflowError
, поскольку оба они называют метод equals
другого объекта и hashCode
. Например, следующая программа будет завершаться 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
Я работаю с устаревшей моделью домена. Моя сериализация существенно исключает родительские отношения в ребенке, а затем фиксирует отношения при десериализации. Имеет ли циркулярные ссылки не обычную вещь в моделях домена? Основополагающим отношением к БД является OneToMany, который был обращен инженерами JBoss в объекты JPA с циклическими ссылками. – Tom