当前位置: 首页 > 面试题库 >

在Java中为具有循环引用的对象实现equals和hashCode

蔚俊人
2023-03-14
问题内容

定义了两个类,以便它们都包含对另一个对象的引用。它们看起来与此类似(这是简化的;在我的实际域模型中,类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;
    }
}

hashCodeequals已通过使用Eclipse中A和B这两个问题的两个场产生的是调用equalshashCode在任一对象方法的结果在StackOverflowError因为它们都调用另一个对象的equalshashCode方法。例如,以下程序将无法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方法中,这样就可以对对象进行真正的深度相等比较,但是我看不到如何解决这个问题。谢谢!


问题答案:

我同意I82的意见,因此您应该避免让B引用他们的父母:这是信息重复,通常只会导致麻烦,但是您可能需要这样做。

即使您将父引用保留在中B,就哈希码而言,您也应该完全忽略父引用,而仅使用的 真正 内部变量B来构建哈希码。

As为只是容器,其价值是由它们的内容,这是包含的值完全确定B,依次类推应他们的哈希键。

如果A是无序集,则必须非常小心,以根据B值(或B哈希码)构建的哈希码不依赖于某些排序。例如,如果哈希码是通过将包含的哈希码B按一定顺序相乘并相乘来构建的,则在计算总和/乘法结果之前,应先按递增顺序对哈希码进行排序。同样,A.equals(o)一定不能依赖Bs
的顺序(如果是无序集合)。

请注意,如果您使用java.util.Collectionin
A,则B通过忽略父引用来固定s哈希码将自动给出有效的A哈希码,因为Collections在默认情况下具有良好的哈希码(有序或无序)。



 类似资料:
  • 我有一个包含循环引用的JavaScript对象定义:它有一个引用父对象的属性。 它还有一些我不想传递给服务器的函数。如何序列化和反序列化这些对象? 我读过这样做的最好方法是使用Douglas Crockford的stringify。但是,我在Chrome中遇到以下错误: 将圆形结构转换为JSON 守则: 这是我为这个问题创建的测试用例。这段代码中有一些错误,但基本上我在对象中有对象,并向每个对象传

  • 我有三个实体,EntityA、EntityB和EntityC,以这样的方式 是否有任何方法或任何库来生成正确的响应bean? 注意:使用lazy不是一个选项,因为在其他一些方法中,我希望获得相关的实体。

  • 问题内容: 我有2张表: 在部门中: numEmpl是主键 numDept是对Departamentos(numDept)的外键引用。在部门中: numDept是主键 numDirect是对Empleados(numEmpl)的外键引用 因此,有一个循环参考。 首先,我创建了表格: 现在,我在它们之间创建引用: 它起作用了,所以现在我尝试插入一些数据: 但是现在它引发了一个错误,告诉我不能在循环引

  • 根据我所读到的, 要使用对象作为hashMap的键,它必须提供正确的重写和equals和hashCode方法的实现。HashMap get(Key k)方法调用Key对象上的hashCode方法,并将返回的hashValue应用到它自己的静态哈希函数中,以找到一个桶位置(备份数组),键和值以名为Entry(Map.Entry)的嵌套类的形式存储在这里。HashMap的内部哈希方法防御质量差的哈希函

  • 或者“为什么Sun/Oracle的家伙每次都强迫我们重写equals()和hashCode()?” 每个人都知道,如果你覆盖一个对象的equals()或hashCode(),你也必须覆盖另一个,因为这两者之间有一个约定: 请注意,每当重写hashCode方法[e.equals()]时,通常有必要重写该方法,以维护hashCode方法的一般约定,即相等的对象必须具有相等的哈希代码。-对象的API文档

  • 问题内容: 给定一个以复杂的,循环的方式相互引用的类实例的集合:垃圾收集器是否可能无法释放这些对象? 我隐约记得过去这是JVM中的问题,但我 认为 这在几年前已解决。但是,在jhat中进行的一些调查显示,循环引用是我现在面临的内存泄漏的原因。 注意:我一直给人以JVM能够解析循环引用并从内存中释放这种“垃圾岛”的印象。 但是,我提出这个问题只是为了看看是否有人发现了任何异常。 问题答案: 循环引用