【问题标题】:Default implementation for hashCode() and equals() for record vs class in JavaJava 中记录与类的 hashCode() 和 equals() 的默认实现
【发布时间】:2025-11-28 08:40:01
【问题描述】:

尝试使用示例代码检查 recordclassequals()hashCode() 的默认行为,但 record 的行为似乎不同strong> 与 class 比较。

这是 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 的实现有更改记录,那么请帮助我了解更改的确切目的以及在哪些情况下使用它会更有帮助。

【问题讨论】:

  • 记录的全部目的是成为一个值对象,所以自动比较是有意义的。

标签: java equals hashcode java-record java-17


【解决方案1】:

简而言之,区别很简单:

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

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

在合理的情况下,Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。 (在某个时间点,hashCode 可能会或可能不会被实现为对象内存地址的某个函数。)

实际上,这意味着任何未覆盖其类型层次结构中任何位置的hashCode 的对象都将返回所谓的“身份哈希码”,它实际上是一个任意但恒定的数字。

对于java.lang.Record it says

当且仅当参数是与此记录相同的记录类的实例,并且此记录的每个组件都等于参数的相应组件时,隐式提供的实现才返回true;否则,返回 false。分量 c 的相等性确定如下:

  • 如果组件是引用类型,当且仅当 Objects.equals(this.c, r.c 将返回 true 时,组件才被视为相等。
  • 如果组件是原始类型,则使用相应的原始包装类 PW(int 的相应包装类是 java.lang.Integer,依此类推),当且仅当 PW.compare 时,组件才被视为相等(this.c, rc) 将返回 0。

除了上面描述的语义之外,隐式提供的实现中使用的精确算法是未指定的,并且可能会发生变化。实现可能会或可能不会使用对列出的特定方法的调用,并且可能会或可能不会按组件声明的顺序执行比较。

(这些分别用于hashCode 方法,equals 方法具有相似的语言)。

更多讨论请见JEP 395: Records

【讨论】: