尝试使用示例代码来检查
equals()
和hashCode()
对于record与class的默认行为,但与class相比,record的行为似乎有所不同。
这里是 record 和 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;
}
}
上述代码执行后输出为:
record equals: true
hashcode objA: 101
hashcode objB: 101
class equals: false
hashcode objA: 935044096
hashcode objB: 396180261
任何人都可以帮我理解
equals
和 hashCode
的记录默认实现的行为与上述有何不同?
如果
equals
和 hashCode
的实施方式有变化以供记录,那么请帮助我了解该变化的确切目的是什么以及在哪些场景下使用它会更有帮助。
简而言之,区别很简单:
equals()
和hashCode()
的默认实现永远不会将两个对象视为java.lang.Object
,除非它们是同一个对象(即它是“对象标识”,即equal
)。记录的 x == y
equals()
的默认实现将考虑所有组件(或字段)并比较它们是否相等(或考虑它们的哈希码)。如果它们全部匹配,则 hashCode()
将返回 .equals()
并且 true
将返回相同的值。
记录的详细信息是:就合理实用而言,Object 类定义的 hashCode 方法为不同的对象返回不同的整数。
实际上,这意味着任何不覆盖其类型层次结构中任何位置的
java.lang.Object.hashCode()
的对象都将返回所谓的“身份哈希码”,它实际上是一个任意但恒定的数字。
至于,它说:隐式提供的实现返回通过组合每个组件的适当哈希值而派生的哈希码值。隐式提供的实现中使用的精确算法未指定,并且可能会在上述限制内发生变化。即使组件值的散列以这种方式保持一致,从应用程序的一次执行到同一应用程序的另一次执行,所得到的整数不需要保持一致。此外,原始类型的组件可能会将其位贡献给哈希码,其方式与其原始包装类的 hashCode 不同。
对于
java.lang.Record.hashCode()
方法;
:Object 类的 equals 方法实现了对象上最具辨别力的可能等价关系;也就是说,对于任何非空引用值 x 和 y,
当且仅当 x 和 y 引用同一个对象(x == y 的值为 true)时,此方法才返回 true。换句话说,在引用相等等价关系下,每个等价类只有一个元素。
java.lang.Object.equals(Object obj)
:
当且仅当参数是与此记录相同的记录类的实例,并且此记录的每个组件等于参数的相应组件时,隐式提供的实现才返回 true;否则,返回 false。分量 c 的相等性确定如下: 如果组件是引用类型,当且仅当 Objects.equals(this.c, r.c 返回 true 时,组件才被视为相等。 如果组件是原始类型,使用相应的原始包装类 PW(int 的相应包装类是 java.lang.Integer 等),当且仅当 PW.compare(this. c, r.c) 将返回 0。 除了上述语义之外,隐式提供的实现中使用的精确算法未指定,并且可能会发生变化。实现可能会也可能不会使用对列出的特定方法的调用,并且可能会也可能不会按照组件声明的顺序执行比较。
有关更多讨论,请参阅
JEP 395:记录。