Почему метод equals(), когда у нас есть оператор ==?
Когда я вижу реализацию equals()
метод это ничего не делает, но то же самое, что ==
делает. Итак, мой вопрос заключается в том, что было необходимо иметь это в качестве отдельного метода, когда мы имеем ==
оператор, который делает то же самое?
8 ответов
Вы не можете перегрузить ==
оператор, но вы можете переопределить equals(Object)
если вы хотите, чтобы он вел себя иначе, чем ==
оператор, т.е. не сравнивать ссылки, но фактически сравнивать объекты (например, используя все или некоторые из их полей).
Кроме того, если вы переопределите equals(Object)
, посмотри на hashCode()
также. Эти два метода должны быть совместимы (т.е. два объекта, которые равны в соответствии с equals(Object)
нужно иметь то же самое hashCode()
), иначе возникнут все виды странных ошибок (например, при добавлении объектов в набор или карту).
==
сравнивает ссылки на объекты и спрашивает, совпадают ли эти две ссылки.
equals()
сравнивает содержимое объекта и спрашивает, представляют ли объекты одно и то же понятие.
В случае примитивов, ==
Оператор проверяет, совпадают ли два значения.
Если это не примитивы, он проверяет, являются ли они двумя указателями (или ссылками), указывающими на один и тот же экземпляр объекта.
equals()
Метод выполняет пользовательскую проверку, которая находится в Object
проверка ссылки, используя ==
, Но в других классах иногда equals()
переопределяется (я не знаю, является ли это правильным прошлым причастием). equals()
должен проверить содержание.
Так, например:
int i0 = 34;
int i1 = 34;
int i2 = 35;
// results
i0 == i1: true
i1 == i0: true
i2 == i0: false
Но если у нас есть не примитивы
String str0 = new String("Hello man!");
String str1 = new String("Hello man!");
String str2 = new String("!nam olleH");
String str2copy = str2;
// Results
str0 == str1: false // Pointer to two different object, so == will give false
str1 == str2: false // Idem
str2 == str2copy: true // So this are two pointers to the same object
str0.equals(str1): true // This are not the same objects, but they are equal
str1 == str1: true // Again: two times a pointer to the same object
Итак, почему str0.equals(str1)
возвращается true
? Потому что класс String имеет переопределение equals()
, И в этом методе он не проверяет, равны ли они, делая return this == obj;
Но в этом методе есть полная проверка. Я не знаю, какой метод они используют для сравнения двух строк, но вот два возможных способа:
- Генерируем из двух строк хеш-код и проверяем, равны ли они (
int == int
) - Проверка символ за символом, если они одинаковы.
Надеюсь, теперь это понятно.
== оператор используется для сравнения ссылок.
Метод equals() определен поверх определения объекта.
Dog d =new Dog();
Collar c =new Collar("Red");
d.setCollar(c);
Dog d2=new Dog();
Collar c2=new Collar("Red");
d2.setCollar(c2);
d2.getCollar() ==d.getCollar()
возвратил бы false, указывая, что у двух собак есть два различных объекта ошейника (предметы). они не имеют тот же самый ошейник.
d2.getCollar().equals(d.getCollar())
верните true, если ошейник определен как [ошейник одинаковый, если цвет ошейника одинаковый] у двух собак одинаковый цветной ошейник.
class Collar{
String color="";
public Collar(String p0){
this.color=p0;
}
boolean equals(Object c){
Collar other=(Collar)c;
return this.color.equals(other.getColor());
}
public String getColor(){
return this.color;
}
}
Существует очень важное различие между ними.
"==" сравнивает экземпляры объекта. Реализация по умолчанию equals() делает это тоже. Пожалуйста, запустите и проанализируйте следующий пример кода:
public class Person{
String name;
public Person(String name){
this.name = name;
}
//overriding equals
public boolean equals( Object obj ) {
if( this == obj )
return true;
if( obj == null )
return false;
if( getClass() != obj.getClass() )
return false;
Person other = (Person) obj;
if( name == null ) {
if( other.name != null )
return false;
} else if( !name.equals( other.name ) )
return false;
return true;
}
}
...
...
Person john1 = new Person("John");
Person john2 = new Person("John");
System.out.println("john1 == john2:" + (john1 == john2));
System.out.println("john1.equals(john2):" + john1.equals(john2));
Как вы можете видеть, "==" вернет false (объекты - это два разных экземпляра Person), тогда как equals вернет true (потому что мы определили, что 2 Person равны, если у них одинаковое имя)
Это сделано для того, чтобы сделать это возможным:
String s1 = new String("foo");
String s2 = new String("foo");
System.out.println(s1 == s2); // false?! Different references!
System.out.println(s1.equals(s2)); // true
Если вы проверите источник String#equals()
вы увидите, что он переопределил Object#equals()
соответственно сравнить внутренний массив символов друг друга (фактическое значение). У многих других классов этот метод также переопределен.
В Java оператор равенства (==) работает с данными двух переменных, если операнды имеют примитивные типы данных. Но если операнды являются объектами, java сравнивает их, используя ссылки, потому что не может выяснить, какое поле или поля объекта сравнивать.
Таким образом, существует только один способ сравнения, основанный на пользовательских полях, который определяется в объекте с помощью переопределения методов equals(), поскольку оператор равенства (==) не может быть переопределен в java, поскольку java не поддерживает переопределение операторов.
Например, если вы хотите сравнить Employee на основе имени, вам нужно определить его логику, переопределив метод equals в классе Employee, как показано ниже:
public class Employee {
private Integer id;
private String name;
@Override
public boolean equals(Object obj) {
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
"string" == "string" вернет false "string".equals("string") вернет true
С o1 == o2 вы сравниваете, что объект 1 является тем же объектом, что и o2 (для справки)
С помощью o1.equals(o2), в зависимости от объекта, метод equals переопределяется и не реализуется с чем-то вроде "return o1 == o2"
Например, вы создаете 2 экземпляра набора. Эти 2 объекта набора являются 2 различными объектами, вы можете добавлять различные элементы в любой из них. set1 == set2 всегда будет возвращать false, но set1.equals (set2) в конечном итоге вернет true, если set2 содержит точно те же элементы, что и set1... и поскольку метод equals переопределяется в классе Set...
Реализация Equals для Set:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set s = (Set) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
}