Идентичность и равенство объектов в Java


В этой короткой статье я буду обсуждать идентичность объектов и равенство объектов в Java.

Идентификация объекта

Когда мы создаем объекты в Java, компьютер сохраняет их в своей памяти. Чтобы иметь возможность найти объект, компьютер назначает ему адрес в памяти. Каждый новый создаваемый объект получает новый адрес. Если эта желтая область представляет собой область памяти компьютера, то синяя область представляет наш объект, хранящийся в памяти. Этому объекту будет дан какой-то адрес.



Чтобы проиллюстрировать эту особенность, давайте представим себе здание, показанное ниже. Если мы посмотрим на здание, то можем задаться вопросом, является ли это Капитолием или просто еще один объект Капитолия. Для проверки мы можем сравнить уникальный адрес этого объекта с адресом Капитолия. Мы бы проверили идентичность нашего объекта, используя’==', оператор equals. Надеюсь, адрес этого дома - "Капитолийский холм, Вашингтон, округ Колумбия", иначе мы смотрим на другой объект.



Теперь давайте объявим три переменные и обсудим их расположение в памяти:

Car myCar1 = new Car("blue");
Car myCar2 = myCar1;
Car myCar3 = new Car("blue");
Мы имеем ссылочные переменные myCar1, myCar2 и myCar3. myCar1 был назначен новый объект Car, как и myCar3, но myCar2 было присвоено значение myCar1. Это различие является ключевым. myCar2 не является новым объектом. Это просто вторая ссылочная переменная, указывающая на один и тот же объект в памяти. Таким образом, хотя у нас есть три переменные, которые мы создали, на самом деле мы разместили только два объекта в памяти.



Теперь давайте возьмем эти ссылочные переменные и сравним их с помощью оператора equals, ‘==’. Когда мы используем оператор equals, мы можем видеть, ссылаются ли обе переменные на один и тот же объект в памяти. Взгляните на три утверждения if ниже:

if(myCar1 == myCar1){ // true
}  
if(myCar1 == myCar2){ // true
}
if(myCar1 == myCar3){ // false 
}
Когда мы сравниваем myCar1 с самим собой, он вычисляется как true, потому что они ссылаются на один и тот же объект в памяти. Аналогично, myCar1 == myCar2 также принимает значение true. Опять же, хотя они являются разными ссылочными переменными, они ссылаются на один и тот же объект в памяти. Наконец, mycar1 == myCar3 вычисляется как false, потому что они указывают на различные объекты в памяти.

Равенство объектов

Другой способ, которым можно проверить равенство, заключается в использовании метода equals (). Метод equals сообщает нам, если два объекта считаются равными. Предположим, что наша программа требует, чтобы два автомобиля были "равны", если они имеют один и тот же цвет. Итак, давайте рассмотрим те же три утверждения if:

if(myCar1.equals(myCar1)){ // true
}  
if(myCar1.equals(myCar2)){ // true
}
if(myCar1.equals(myCar3){ // false 
}
Основываясь на том, что вы читали до сих пор, вы могли бы подумать, что все три утверждения будут оцениваться как истинные . Однако это не так, как работает метод по умолчанию equals (). Если вы посмотрите на метод по умолчанию equals () класса объектов, он фактически вызывает == , предоставляя ему ту же функциональность, что и просто говоря obj1 == obj2 .

public boolean equals(Object obj) {
    return (this == obj);
}
Очевидно, что это не то, чего мы хотим. В нашем примере мы хотим судить, равны ли два автомобиля на основе их цвета. Таким образом, нам придется переопределить метод equals() :

@Override
public boolean equals(Object obj) {
     if (this == obj) {
          return true;
     }
     if (obj == null) { 
         return false;
     }
     if (getClass() != obj.getClass()) {
          return false;
     }
     Car other = (Car) obj;
     return this.color.equals(other.color);}

@Override
public int hashCode() {
    return color.hashCode();
}
Теперь мы выражаем в коде то, что мы считаем равным или неравным. Опять же, это полностью зависит от того, что наш клиент считает равным или неравным. Мы переопределяем эти методы не потому, что создатели Java думали, что это будет хорошей идеей, а потому, что не было никакого другого варианта. Когда они писали класс объектов, они на самом деле не имели в виду наш класс автомобилей и конкретный способ, которым мы будем их сравнивать, поэтому они придумали общий метод, который они приветствуют нас изменить.

Вы также можете заметить, что я не просто перезаписал метод equals(). Я также переопределил hashCode() метод. Java указывает, что равные объекты также должны иметь равные хэшкоды.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, java




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Расширения для браузера Chrome: быстро и просто
Несколько советов по разработке программ
Верстка с помощью jQuery