Освойте использование равенства с помощью следующих примеров
package cn.galc.test;public class TestEquals { public static void main(String[] args) { /** * Здесь метод конструкции Cat() используется для создания двух новых котов в куче памяти. * Два кота. Цвет, вес и высота одинаковы, * но c1 и c2 никогда не будут равны. Это потому, что c1 и c2 являются ссылочными объектами двух кошек в куче памяти, *. Он содержит адреса, по которым можно найти двух котов, но поскольку два кота хранятся в двух разных областях динамической памяти, * c1 и c2 содержат разные адреса, поэтому c1 и c2 никогда не будут равны. */ Cat c1 = new Cat(1, 1, 1); Cat c2 = new Cat(1, 1, 1); System.out.println("Результат c1==c2: "+(c1==) c2 ));//false System.out.println("Результат c1.equals(c2): "+c1.equals(c2));//false }}class Cat { int color, вес, высота; общественный Cat (int цвет, int вес, int высота) { this.color = color; this.weight = вес; this.height = высота }}Нарисуйте диаграмму анализа памяти, чтобы проанализировать результаты сравнения c1 и c2.
программа:
Кот c1 = новый кот(1,1,1); Кот c2 = новый кот(1,1,1);
После выполнения расположение в памяти будет таким, как показано ниже:
c1 указывает на объект, а c2 также указывает на объект. C1 и c2 содержат адреса, хранящиеся в куче этих двух объектов Cat. Поскольку два объекта Cat расположены в разных областях хранения, c1 и c2 содержат адреса. определенно не равны, поэтому два ссылочных объекта c1 и c2 определенно не равны. Следовательно, если вы выполните: «System.out.println(c1==c2);» результат печати обязательно будет ложным. Таким образом, вы создаете два объекта с помощью new. Не волнуйтесь, ссылки на два объекта никогда не будут одинаковыми. Если они одинаковы, один из них будет перезаписан. Если c1 равен c2, сравнивается содержимое, содержащееся в двух ссылках c1 и c2, поскольку ссылки двух объектов, созданных new, никогда не совпадают, поэтому содержимое двух ссылок c1 и c2 также никогда не бывает одинаковым. Следовательно. c1 никогда не может быть равным c2. Следовательно, сравнение ссылок двух объектов никогда не сможет сделать эти два объекта равными или идентичными.
Чтобы определить, равны ли два объекта, вы не можете сравнить, равны ли ссылки двух объектов. Вы никогда не получите равный результат, поскольку ссылки двух объектов никогда не будут равны, поэтому правильный метод сравнения — напрямую сравнивать их. два объекта и сравнить, одинакова ли сущность двух объектов, то есть одинаково ли содержимое двух объектов. Определите, равны ли два объекта, сравнивая значения атрибутов двух объектов. такие же.
Класс Object предоставляет методquals() для сравнения идентичности содержимого двух объектов, поэтому мы можем использовать этот метод для сравнения того, являются ли два объекта логически «равными». Например: c1.equals(c2); Вот вызов метода Equals(), унаследованного от класса Object. Если обратиться к документации API, определение метода Equals в классе Object выглядит следующим образом:
общедоступное логическое равенство (Object obj)
Реализация метода Equals() по умолчанию, представленная в классе Object, предназначена для сравнения ссылки текущего объекта и ссылки, которую вы хотите сравнить, чтобы увидеть, указывают ли они на один и тот же объект, что аналогично «c1==c2». ". , "c1.equals(c2)" и "c1==c2" полностью эквивалентны. Следовательно, непосредственное использование унаследованного методаquals() не может напрямую сравнить, одинаково ли содержимое двух объектов. По этой причине мы должны переопределить методquals() и изменить реализацию этого метода по умолчанию.
Затем перепишите унаследованный метод равенства() в классе Cat:
class Cat { int color,weight,height; public Cat(intcolor,intweight,intheight) { this.color = color; this.height = height } /** * Это переписывание равенства; Метод Equals(), унаследованный от класса Object, изменяет реализацию этого метода по умолчанию. * Используйте нашу собственную реализацию, чтобы определить, являются ли два объекта логически равными. * Здесь мы определяем, что если цвет, вес и рост двух кошек одинаковы, * тогда мы считаем, что эти две кошки логически идентичны, то есть две кошки «равны». */ public booleanquals(Object obj){ if (obj==null){ return false } else{ /** * instanceof — оператор объекта. * Оператор объекта используется для определения принадлежности объекта экземпляру указанного класса или указанного подкласса. * Оператор объекта представляет собой комбинированное слово «instanceof». * Этот оператор является бинарным. Выражение слева — это объект, а выражение справа — класс. * Если объект слева — это объект, созданный классом справа, результатом операции является. правда, в противном случае это ложь. */ if (obj instanceof Cat){ Cat c = (Cat)obj; if (c.color==this.color && c.weight==this.weight && c.height==this.height){ return true; } } } вернуть ложь }} В это время выполните команду печати в основном методе:
public static void main(String[] args) { /** * Здесь метод конструкции Cat() используется для создания двух новых котов в куче памяти * Цвет, вес и рост этих двух котов одинаковы. . * Но c1 и c2 никогда не будут равны. Это связано с тем, что c1 и c2 являются ссылочными объектами двух котов в куче памяти, * содержащей адреса, по которым можно найти двух котов, а также потому, что эти два кота хранятся в памяти. куча памяти В двух разных пространствах * Таким образом, c1 и c2 содержат разные адреса, поэтому c1 и c2 никогда не будут равны. */ Cat c1 = new Cat(1, 1, 1); Cat c2 = new Cat(1, 1, 1); System.out.println("Результат c1==c2: "+(c1==) c2 ));//false System.out.println("Результат c1.equals(c2): "+c1.equals(c2));//true }Результат, полученный на этот раз, отличается от результата, полученного в прошлый раз без переопределения методаquals():
«System.out.println(c1 == c2);» Результат печати по-прежнему является ложным, поскольку содержимое ссылок двух объектов сравнивается. Разумеется, содержимое двух ссылок не равно и никогда не будет равным. равны, поэтому напечатанный результат должен быть ложным.
«System.out.println(c1.equals(c2));» Напечатанный результат верен, поскольку мы переписали методquals() в классе Cat и изменили реализацию этого метода по умолчанию. Мы изменили реализацию. метод Изменить только на Если эти два объекта действительно существуют и оба являются кошками, а их цвет, рост и вес одинаковы, то две кошки логически идентичны и совершенно одинаковы. То есть эти две кошки «равны». Таким образом, результат, напечатанный здесь, верен.
Итак, как сравнить два строковых объекта на равенство?
Посмотрите на следующий пример:
public class TestEquals { public static void main(String args[]){ String s1 = new String("hello String" s2 = new String("hello System.out.println("s1 == s2 result Is) : "+(s1 == s2));//ложь System.out.println("Результат s1.equals(s2): "+s1.equals(s2));//true }}На этот раз два строковых объекта сравниваются на равенство:
System.out.println(s1 == s2);
Напечатанный результат по-прежнему является ложным, поскольку здесь сравниваются ссылки двух строковых объектов s1 и s2. Ссылки двух объектов никогда не будут равны, поэтому напечатанный результат является ложным.
System.out.println(s1.equals(s2));
Напечатанный результат верен, поскольку наследование от класса Object переписано в классе String (все классы наследуются от класса Object, и класс String, конечно, не является исключением. Если вы наследуете от родительского класса, у вас есть все атрибутов и методов родительского класса, поэтому класс Sting также имеет метод Equals(), а унаследованный метод Equals() также был переписан), изменив реализацию этого метода по умолчанию.
В классе String реализация методаquals() переопределяется следующим образом: сравнивается текущий строковый объект с указанным строковым объектом. Указанный строковый объект не может быть пустым, а последовательность символов этого объекта совпадает с текущей строкой. . Строковые последовательности объектов одинаковы. Если эти условия соблюдены, то два строковых объекта равны.
Следовательно, s2 здесь соответствует условию, поэтому напечатанный результат верен.
В дальнейшем, сравнивая на равенство два объекта в определенном классе, сначала обратитесь к документации API, чтобы узнать, не переопределил ли этот класс методquals(), унаследованный от класса Object. Если метод Equals() переопределен, то при сравнении равенства двух объектов вызывается переопределенный метод Equals(). Если он не переопределен, то метод, унаследованный от класса Object, вызывается напрямую. использует реализацию методаquals() по умолчанию для сравнения равенства двух объектов. Таким образом, каждый класс может при необходимости переопределить метод равенства(), унаследованный от класса Object.
Для поиска определенного класса в документе API, если класс можно использовать напрямую, без введения пакета, тогда этот класс должен находиться в пакете java.lang. Например, класс String здесь можно использовать напрямую, поэтому класс String. должно быть. Он находится в пакете java.lang. При использовании определенного класса проверьте, какой пакет импортирует класс, а затем перейдите к пакету, чтобы найти класс. Классы, пакеты которых не нужно импортировать, должны находиться в java.lang. Чтобы найти его, перейдите непосредственно в java.lang. .
Обычно при проектировании класса нам необходимо переопределить метод равенства родительского класса. При переписывании этого метода нам необходимо проектировать его в соответствии со следующими правилами:
1. Рефлексивность: для любого ссылочного значения X возвращаемое значение x.equals(x) должно быть истинным.
2. Симметрия: для любого опорного значения x, y, если и только если возвращаемое значение y.equals(x) истинно, возвращаемое значение x.equals(y) должно быть истинным;
3. Транзитивность: если x.equals(y)=true, y.equals(z)=true, то x.equals(z)=true.
4. Согласованность. Если объекты, участвующие в сравнении, не изменяются, результат сравнения объектов также не должен меняться.
5. Невозможность обнуления: для любого ненулевого ссылочного значения X возвращаемое значение x.equals(null) должно быть ложным.
Например:
люди общественного класса {частное String firstName; частное int age; public String getFirstName () { return firstName; } public void setFirstName (String firstName) { this.firstName = firstName; } public String getLastName () { return LastName; } Public void setLastName(String LastName) { this.lastName = LastName } public int getAge() { return age } public void setAge(int age) { this.age = age; } @Override public booleanquals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Peopleother = (People) obj; if (age !=other.age) return false; if (firstName == null) { if (other.firstName != null) return false } else if; (!firstName.equals(other.firstName)) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false ; вернуть истину }}
В данном примере мы оговариваем, что человек является одним и тем же человеком, если его фамилия, имя и возраст совпадают. Конечно, вы также можете добавить другие атрибуты. Например, идентификационный номер должен быть таким же, чтобы быть оцененным как одно и то же лицо. Затем вы можете добавить оценку идентификационного номера в методе равенства!
Резюме: Чтобы сравнить, равны ли два объекта, мы используем метод Equals(). Условия для определения равенства двух объектов определяются нами после переписывания реализации метода Equals(), чтобы метод Equals() мог это сделать. использовать более гибко. Сравнивайте два объекта одного и того же класса в разных классах, чтобы убедиться, что они равны.