-3

尝试使用示例代码检查记录与类的默认行为,记录equals()行为似乎不同。hashCode()

这是记录类的代码示例

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

谁能帮我理解记录s default implementation for 等于andhashCode 的行为与上述不同吗?

如果记录equalshashCode实施发生变化,那么请帮助我了解该变化的确切目的以及在哪些场景中使用它会更有帮助。

4

1 回答 1

13

简而言之,区别很简单:

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

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

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

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

java.lang.Record说:

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

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

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

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

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

于 2021-09-26T08:23:18.677 回答