'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.
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 records default implementation for
equalsand
hashCode` behaves differently as above?
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.
Solution 1:[1]
In a nutshell the difference is simple:
- the default implementation of
equals()
andhashCode()
forjava.lang.Object
will never consider two objects asequal
unless they are the same object (i.e. it's "object identity", i.e.x == y
). - the default implementation of
equals()
andhashCode()
for records will consider all components (or fields) and compare them for equality (or consider them for the hash code). If they all match then.equals()
will returntrue
andhashCode
will return the same values.
The details documented details for java.lang.Object
are:
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.)
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.
And for 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.
(Those are for the respective hashCode
methods, the equals
methods have similar language).
For more discussion, see JEP 395: Records.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sean Bright |