Вы не можете перегрузить оператор ==
, но можете переопределить equals (Object)
, если хотите он должен вести себя иначе, чем оператор ==
, т.е. не сравнивать ссылки, а фактически сравнивать объекты (например, используя все или некоторые из их полей).
Кроме того, если вы переопределите equals (Object)
, обратите внимание на hashCode ()
. Эти два метода должны быть совместимы (т. Е. Два объекта, которые равны согласно equals (Object)
, должны иметь одинаковый hashCode ()
), в противном случае возникнут все виды странных ошибок. (например, при добавлении объектов в набор или карту).
Между ними есть очень важное различие.
"==" сравнивает экземпляры объектов. Реализация 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 (потому что мы определили, что два человека равны, если у них одинаковое имя)
== используется для сравнения ссылок.
Метод
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())
возвращает истину, если ошейник определен как [Ошейник одинакового цвета, если цвет ошейника одинаковый] у двух собак ошейник одинакового цвета.
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;
}
}
Это сделано для того, чтобы сделать это возможным:
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()
соответствующим образом, чтобы сравнивать внутренний массив символов друг друга (фактическое значение). Многие другие классы также переопределяют этот метод.
В случае примитивов оператор ==
проверяет, совпадают ли два значения .
Если это не примитивы, он проверяет, являются ли они двумя указателями (или ссылками ) , указывающими на один и тот же экземпляр объекта.
Метод equals ()
выполняет пользовательскую проверку, которая в объекте
проверяет ссылку, используя ==
. Но в других классах иногда 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()
сравнивает объект содержимое и спрашивает, представляют ли эти объекты одну и ту же концепцию.
"строка" == "строка" вернет ложь "строка". Equals ("строка") вернет истину
С 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
}