简体   繁体   English

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

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

Tried with sample code to check default behaviour of equals() and hashCode() for record vs class , but it seems behave differently for record compare to class .尝试使用示例代码来检查recordclassequals()hashCode()的默认行为,但recordclass相比似乎表现不同。

Here is code sample for record and class这是记录的代码示例

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;
    }
}

After execution output for above code is:上述代码执行后输出为:

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

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

Can anyone please help me to understand how record s default implementation for equals and hashCode` behaves differently as above?任何人都可以帮助我理解记录s default implementation for等于and hashCode` 的行为与上述不同吗?

And if there is a change in the equals and hashCode implementation for record, then please help me to understand what exactly the purpose of that change and in which scenarios it will be more helpful to use.如果equalshashCode实现有变化以备记录,那么请帮助我了解该变化的确切目的以及在哪些情况下使用它会更有帮助。

In a nutshell the difference is simple:简而言之,区别很简单:

  • the default implementation of equals() and hashCode() for java.lang.Object will never consider two objects as equal unless they are the same object (ie it's "object identity", ie x == y ). java.lang.Objectequals()hashCode()的默认实现永远不会认为两个对象equal ,除非它们是同一个对象(即它是“对象标识”,即x == y )。
  • the default implementation of equals() and hashCode() for records will consider all components (or fields) and compare them for equality (or consider them for the hash code).记录的equals()hashCode()的默认实现将考虑所有组件(或字段)并比较它们是否相等(或考虑它们的哈希码)。 If they all match then .equals() will return true and hashCode will return the same values.如果它们都匹配,则.equals()将返回true并且hashCode将返回相同的值。

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

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。 (The hashCode may or may not be implemented as some function of an object's memory address at some point in time.) (在某个时间点,hashCode 可能会或可能不会被实现为对象内存地址的某个函数。)

In practice this means that any object which doesn't override hashCode anywhere in its type hierarchy will return what is called the "identity hash code" which is effectively an arbitrary but constant number.实际上,这意味着任何在其类型层次结构中的任何地方都没有覆盖hashCode的对象将返回所谓的“身份哈希码”,它实际上是一个任意但恒定的数字。

And for java.lang.Record it says :对于java.lang.Record它说

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;当且仅当参数是与此记录相同的记录类的实例,并且此记录的每个组件都等于参数的相应组件时,隐式提供的实现才返回 true; otherwise, false is returned.否则,返回 false。 Equality of a component c is determined as follows:分量 c 的相等性确定如下:

  • If the component is of a reference type, the component is considered equal if and only if Objects.equals(this.c, rc) would return true.如果组件是引用类型,则当且仅当 Objects.equals(this.c, rc) 返回 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, rc) would return 0.如果组件是原始类型,则使用相应的原始包装类 PW(int 的相应包装类是 java.lang.Integer,依此类推),当且仅当 PW.compare(this. c, rc) 将返回 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.实现可能会或可能不会使用对列出的特定方法的调用,并且可能会或可能不会按组件声明的顺序执行比较。

(Those are for the respective hashCode methods, the equals methods have similar language). (这些是针对各自的hashCode方法, equals方法具有相似的语言)。

For more discussion, see JEP 395: Records .有关更多讨论,请参阅JEP 395:记录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM