Реализация equals и hashCode для объектов с циклическими ссылками в Java

У меня определены два класса, так что они оба содержат ссылки на другой объект. Они выглядят одинаково к этому (это упрощено; в моей реальной модели предметной области класс A содержит список B, и каждый B имеет обратную ссылку на родительский A):

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 и равняется были сгенерированы Eclipse с использованием обоих полей A и B. Проблема в том, что вызов метода equals или hashCode для любого объекта приводит к ошибке 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 , чтобы это было действительно глубокое сравнение объекта на равенство, но я не понимаю, как я могу решить эту проблему.Спасибо!

33
задан Tom 14 January 2012 в 15:52
поделиться