在Java中交叉引用类上覆盖equals / hashCode会导致StackOverflowError [英] Overriding equals/hashCode on cross referencing classes in Java causes StackOverflowError

查看:300
本文介绍了在Java中交叉引用类上覆盖equals / hashCode会导致StackOverflowError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个代表两个不同数据库实体的类。他们在db中的关系为1:m,它在类结构中表示如下:

I have two classes that represent two different database entities. Their relationship is 1:m in db and it is represented in class structures something like this:

public class Company {

    private List<Employee> employees;

    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }

}

public class Employee {

    private Company company;

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

}

现在我要覆盖等于/这些类的hashCode。 Eclipse为我生成以下代码:

Now I want to override equals/hashCode on these classes. Eclipse generates the following code for me:

public class Company {

    private List<Employee> employees;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((employees == null) ? 0 : employees.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Company other = (Company) obj;
        if (employees == null) {
            if (other.employees != null)
                return false;
        } else if (!employees.equals(other.employees))
            return false;
        return true;
    }

}

public class Employee {

    private Company company;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((company == null) ? 0 : company.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (company == null) {
            if (other.company != null)
                return false;
        } else if (!company.equals(other.company))
            return false;
        return true;
    }

}

如果我运行以下测试:

If I run the following test:

public class EqualsTest {

    @Test
    public void testEquals() {

        Company company1 = new Company();
        Employee employee1 = new Employee();

        employee1.setCompany(company1);
        company1.setEmployees(Arrays.asList(employee1));

        Company company2 = new Company();
        Employee employee2 = new Employee();

        employee2.setCompany(company2);
        company2.setEmployees(Arrays.asList(employee2));

        assertThat(company1, is(company2));
    }

}

我希望它能通过,因为两者都是company1和company2有相同的员工列表,但是它失败了StackOverflowError:

I expect it to pass because both company1 and company2 have equal lists of employees, but it fails with StackOverflowError:

java.lang.StackOverflowError
    at java.util.AbstractList$Itr.<init>(AbstractList.java:318)
    at java.util.AbstractList$Itr.<init>(AbstractList.java:318)
    at java.util.AbstractList$ListItr.<init>(AbstractList.java:377)
    at java.util.AbstractList.listIterator(AbstractList.java:315)
    at java.util.AbstractList.listIterator(AbstractList.java:284)
    at java.util.AbstractList.equals(AbstractList.java:502)
    at com.test.Company.equals(Company.java:37)
    at com.test.Employee.equals(Employee.java:35)
    at java.util.AbstractList.equals(AbstractList.java:507)
    at com.test.Company.equals(Company.java:37)
    at com.test.Employee.equals(Employee.java:35)
    at java.util.AbstractList.equals(AbstractList.java:507)
    at com.test.Company.equals(Company.java:37)
    at com.test.Employee.equals(Employee.java:35)
        ...

我知道这种失败的原因是类中的交叉引用,因此是equals / hashCode方法。但是我应该如何实现equals / hashCode以避免不定式递归呢?

I understand that the reason for this failure is cross reference in classes and thus equals/hashCode methods. But how should I implement equals/hashCode to avoid infinitive recursion?

推荐答案

现在,定义了公司的身份完全由其员工。同样,员工的身份仅由其公司定义。您是否看到这会导致相互逻辑依赖?

As it is now, the identity of a company is defined solely by its employees. Likewise, the identity of an employee is defined solely by its company. Do you see how that leads to a mutual logical dependency?

您需要在代码中打破逻辑依赖关系。您如何在逻辑上唯一地识别公司和员工?通常,您可以使用某种有意义的唯一标识符来执行此操作:名称(字符串),数字(int / long)或一些类似的基本字段组合。

You need to break that logical dependency in your code. How would you logically uniquely identify a company and an employee? Typically you'd do this with some sort of meaningful unique identifier: a name (string), a number (int/long), or some similar combination of primitive fields.

这篇关于在Java中交叉引用类上覆盖equals / hashCode会导致StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆