【问题标题】:How default .equals and .hashCode will work for my classes?默认 .equals 和 .hashCode 将如何适用于我的课程?
【发布时间】:2011-05-09 21:41:33
【问题描述】:

假设我有自己的班级

public class MyObj { /* ... */ }

它有一些属性和方法。它不实现equals,不实现hashCode。

一旦我们调用equals和hashCode,默认的实现是什么?来自对象类?它们是什么?默认 equals 将如何工作?默认 hashCode 将如何工作以及返回什么? == 只会检查它们是否引用同一个对象,所以很简单,但是 equals() 和 hashCode() 方法呢?

【问题讨论】:

    标签: java object equals hashcode equality


    【解决方案1】:

    是的,默认实现是 Object 的(一般来说;如果您从重新定义 equals 和/或 hashCode 的类继承,那么您将使用该实现代替)。

    来自文档:

    equals

    Object 类的 equals 方法实现了对象上最有区别的可能等价关系;也就是说,对于任何非空引用值 x 和 y,此方法返回 当且仅当 x 和 y 引用同一个对象时才为真(x == y 的值为真)。

    hashCode

    在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但 JavaTM 编程语言不需要这种实现技术。)

    【讨论】:

    【解决方案2】:

    来自 JVM 实现之一中的 Object

    public boolean equals(Object object) {
        return this == object;
    }
    
    public int hashCode() {
        return VMMemoryManager.getIdentityHashCode(this);
    }
    

    在这两种情况下,它只是比较相关对象的内存地址。

    【讨论】:

    • 它来自哪个版本的 JDK?在v6u23 eapublic native int hashCode();
    • @kha - 你说得对,我想我找到了一个本地实现,看看它实际上做了什么
    • “在这两种情况下,它只是比较相关对象的内存地址。”:HotSpot returns a random number per default 作为哈希值。另请参阅this blog entry
    【解决方案3】:

    Object中有equals()hashCode()的默认实现。如果您不提供自己的实现,则将使用这些实现。对于equals(),这意味着== 比较:只有当它们是完全相同的对象时,它们才会相等。对于hashCode()Javadoc 有很好的解释。

    有关详细信息,请参阅 Effective Java,Chapter 3 (pdf),第 8 项。

    【讨论】:

      【解决方案4】:

      是的,来自Object 类,因为您的类隐式扩展了 Object。 equals 只返回 this == objhashCode 实现是本机的。只是一个猜测 - 它返回指向对象的指针。

      【讨论】:

      • 它是指向位于内存中的对象的指针,但它不是对象的内存地址。 GC 可以在内存中移动对象,并且哈希码将保持不变。
      • @Jeremy 谢谢。 stackoverflow.com/questions/2427631/… 可能很有趣。
      【解决方案5】:

      如果您不提供自己的实现,则将使用从 Object 派生的实现。没关系,除非您打算将类实例放入即 HashSet (任何实际使用 hashCode() 的集合),或者需要检查对象相等性的东西(即 HashSet 的 contains() 方法)。否则它将无法正常工作,如果这是您所要求的。

      借助来自Apache Commons LangHashCodeBuilderEqualsBuilder,您可以很容易地提供这些方法的实现。

      【讨论】:

      • (a) 为什么说 Object 类的“equals”默认实现不能与 HashSet 一起正常工作?这与此页面上的其他答案相矛盾。 (b) 感谢 Commons Lang 链接。
      • @Basil:我认为这并不矛盾。当然默认实现会起作用......不知何故,但不是你期望的方式。也就是说,由于 equals() 使用引用相等,因此在默认实现的眼中,两个相同的对象将是“不同的”。结果,您最终可能会在您的 Set 中拥有完全相同事物的两个不同实例。而 Sets 的典型用法是当您想要消除重复项时......
      • @PawełDyda:对于可变类型,默认行为通常是正确的。如果FooBar 是对可变类型的两个不同实例的引用,并且存在一种方法(例如SomeMutatingMethod)使得Foo.SomeMutatingMethod() 不会像Foo 那样影响Bar,这种差异应该足以将对象视为不平等。
      【解决方案6】:

      IBM 的 developerworks 说:

      在这个默认实现下,两个 仅当引用相等时 指的是完全相同的对象。 同样,默认实现 Object 提供的 hashCode() 是 通过映射内存地址导出 对象的整数值。

      但是,为了确定特定供应商的 Java 版本的确切实现细节,最好查看源代码(如果可用)

      【讨论】:

        猜你喜欢
        • 2021-11-18
        • 1970-01-01
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-08
        • 1970-01-01
        • 2019-06-02
        相关资源
        最近更新 更多