реализация по умолчанию для hashcode () и equals () для записи vs класса в Java
Пытался с образцом кода проверить поведение 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
Может ли кто-нибудь помочь мне понять, как реализация записи по умолчанию для equals и hashcode ведет себя по-разному, как указано выше?
и если есть изменение в equals и реализации хэш-кода для записи. тогда, пожалуйста, помогите мне понять, в чем именно заключается цель этого изменения и в каких сценариях оно будет более полезным.
Заранее спасибо!!
1 ответ
В двух словах разница проста:
- реализация по умолчанию и for никогда не будет рассматривать два объекта как
equal
если они не являются одним и тем же объектом (т.е. это «идентичность объекта», т.е.x == y
). - реализация по умолчанию
equals()
а такжеhashCode()
для записей будет рассматривать все компоненты (или поля) и сравнивать их на равенство (или рассматривать их для хэш-кода). Если все они совпадают, тогда.equals()
вернусьtrue
и вернет те же значения.
Подробно задокументированные детали для
java.lang.Object
находятся:
Насколько это разумно практично, метод hashCode, определенный классом Object, действительно возвращает отдельные целые числа для отдельных объектов. (Хэш-код может или не может быть реализован как некоторая функция адреса памяти объекта в какой-то момент времени.)
На практике это означает, что любой объект, который не переопределяет нигде в своей иерархии типов, будет возвращать так называемый «хэш-код идентичности», который фактически является произвольным, но постоянным числом.
И для java.lang.Record
он говорит :
Неявно предоставленная реализация возвращает истину тогда и только тогда, когда аргумент является экземпляром того же класса записи, что и эта запись, и каждый компонент этой записи равен соответствующему компоненту аргумента; в противном случае возвращается false. Равенство компонента c определяется следующим образом:
- Если компонент относится к ссылочному типу, он считается равным тогда и только тогда, когда Objects.equals (this.c, rc вернет true.
- Если компонент относится к примитивному типу с использованием соответствующего примитивного класса-оболочки PW (соответствующий класс-оболочка для int - это java.lang.Integer и т. Д.), Компонент считается равным тогда и только тогда, когда PW.compare (this. c, rc) вернет 0.
Помимо семантики, описанной выше, точный алгоритм, используемый в неявно предоставленной реализации, не определен и может быть изменен. Реализация может использовать или не использовать вызовы конкретных перечисленных методов, а также может выполнять или не выполнять сравнения в порядке объявления компонентов.
(Это для соответствующих
hashCode
методы,
equals
методы имеют похожий язык).