记录的 hashCode() 和 equals() 的默认实现与 Java 中的 class

Default implementation for hashCode() and equals() for record vs class in Java

尝试使用示例代码来检查 equals()hashCode() 对于 recordclass[= 的默认行为36=],但 recordclass.

的行为似乎有所不同

这是 recordclass

的代码示例
public class EqualsAndHashcode {
    public static void main(String[] args) {
        var employeeA = new Employee(101);
        var employeeB = new Employee(101);
        var employeeAClass = new EmployeeClass(102);
        var employeeBClass = new EmployeeClass(102);
        var printStream = System.out;
        printStream.println("record equals: " + employeeA.equals(employeeB) + "\nhashcode objA: " + employeeA.hashCode() + "\nhashcode objB: " + employeeB.hashCode());
        printStream.println("\nclass equals: " + employeeAClass.equals(employeeBClass) + "\nhashcode objA: " + employeeAClass.hashCode() + "\nhashcode objB: " + employeeBClass.hashCode());
    }
}

record Employee(int empId) {
}

class EmployeeClass {
    int empId;

    EmployeeClass(int empId) {
        this.empId = empId;
    }
}

以上代码执行后输出为:

record equals: true
hashcode objA: 101
hashcode objB: 101

class equals: false
hashcode objA: 935044096
hashcode objB: 396180261

任何人都可以帮助我理解 records default implementation for equalsandhashCode` 的行为与上述不同吗?

并且如果 equalshashCode 实现中有更改记录,那么请帮助我了解该更改的确切目的是什么以及在哪些情况下会更有帮助使用。

简而言之,区别很简单:

  • equals()hashCode() 对于 java.lang.Object 的默认实现永远不会将两个对象视为 equal 除非它们是同一个对象(即它是“对象标识” , 即 x == y).
  • 记录的 equals()hashCode() 的默认实现将考虑所有组件(或字段)并比较它们是否相等(或考虑它们的哈希码)。如果它们都匹配,那么 .equals() 将 return truehashCode 将 return 相同的值。

记录的详细信息 details for java.lang.Object 是:

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (The hashCode may or may not be implemented as some function of an object's memory address at some point in time.)

在实践中,这意味着任何不覆盖 hashCode 其类型层次结构中任何地方的对象都将 return 所谓的“身份哈希码”,它实际上是一个任意但恒定的数字.

对于java.lang.Record it says

The implicitly provided implementation returns true if and only if the argument is an instance of the same record class as this record, and each component of this record is equal to the corresponding component of the argument; otherwise, false is returned. Equality of a component c is determined as follows:

  • If the component is of a reference type, the component is considered equal if and only if Objects.equals(this.c, r.c) would return true.
  • If the component is of a primitive type, using the corresponding primitive wrapper class PW (the corresponding wrapper class for int is java.lang.Integer, and so on), the component is considered equal if and only if PW.compare(this.c, r.c) would return 0.

Apart from the semantics described above, the precise algorithm used in the implicitly provided implementation is unspecified and is subject to change. The implementation may or may not use calls to the particular methods listed, and may or may not perform comparisons in the order of component declaration.

(这些是针对各自的 hashCode 方法,equals 方法具有相似的语言)。

有关更多讨论,请参阅 JEP 395: Records