3

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

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;
    }

}

现在我想在这些类上覆盖 equals/hashCode。Eclipse 为我生成以下代码:

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;
    }

}

如果我运行以下测试:

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 而失败:

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)
        ...

我了解此失败的原因是类中的交叉引用,因此等于/hashCode 方法。但是我应该如何实现equals/hashCode来避免不定式递归呢?

4

4 回答 4

4

就像现在一样,公司的身份完全由其员工定义。同样,员工的身份仅由其公司定义。你看到这是如何导致相互逻辑依赖的吗?

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

于 2012-03-29T03:39:51.683 回答
2

恕我直言,有 2 个版本可用。我认为公司应该是“领导”类,存储员工。

  1. 版本:在员工平等中,使用“==”来检查公司的对象平等(不是很好)
  2. 版本:为您的公司分配一个唯一的 ID,并比较员工中只有该公司 ID 等于

hth

于 2012-03-29T03:40:10.397 回答
1

不要在 Company.equals 方法中比较员工列表。Company 的其他属性是否有意义并且可用于在 equals 中执行比较,例如名称?还是股票代码?

于 2012-03-29T03:41:42.337 回答
1

Company您无意中在和之间建立了递归依赖关系Employee。该Company#hashCode()方法需要计算每个 Employee 的单独 hashcode,并且该Employee#hashCode()方法依赖于 Company 的 hashcode,导致无限递归。

公司对象的哈希码不应依赖于其中的员工。哈希码在某种意义上是对象的“身份”,当有新员工加入时,它不应该改变。员工也一样。员工的身份不应仅仅因为他/她搬到另一家公司而改变。

您必须根据一些有意义的身份属性重新定义这些方法。您的代码没有显示它,但两者都Company必须Employee有一些其他成员变量,例如名称。基于该属性的 hashCode 和 equals 实现。

于 2012-03-29T03:45:20.020 回答