реализация по умолчанию для 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 методы имеют похожий язык).

Другие вопросы по тегам