Metoda equals()
Porównuje zawartość obiektu oraz adresy obiektów w pamięci (referencje), a nie tylko same referencje.
UWAGA:
Metoda ta zachowuje się inaczej w przypadku obiektów klasy String, a inaczej w przypadku obiektów innych klas, poniważ w przypadku obiektów klasy String Java wykorzystuje mechanizm optymalizacyjny i nie tworzy dodatkowych obiektów, jeśli dwa łańcuchy znaków są identyczne.
public class EqualsMethodForStringTestProgram {
public static void main( String[] args ) {
String object1 = new String("String pierwszy");
String object2 = new String("String pierwszy");
if( object1 == object2 ) // false, ponieważ są to dwa różne adresy
System.out.println( "object1 == object2" );
if( object1.equals( object2 ) ) // true, ponieważ w wypadku obiektów typu String Java optymalizuje kod i unika tworzenia osobnych obiektów dla takich samych ciągów znaków
System.out.println( "object1.equals( object2 )" );
}
}
Przykład dla klasy innej niż String:
public class HashCodeExample {
public static void main( String[] args ) {
MojaKlasa object1 = new MojaKlasa( "Nazwa", 222 );
MojaKlasa object2 = new MojaKlasa( "Nazwa", 222 );
System.out.println( "object1.equals(object2): " + object1.equals(object2) ); //false
}
}
class MojaKlasa {
String name;
int value;
public MojaKlasa( String name, int value ) {
this.name = name;
this.value = value;
}
}
Jak widać, w takiej sytuacji metoda equals() porównuje oprócz zawartości także adres obiektu.
Metoda equals() jest dostępna w klasie java.lang.Object. Każdy obiekt utworzony w Javie ma obiekt Object na samym szczycie hierarchii dziedziczenia i dlatego metoda equals() jest dostępna w każdym obiekcie.
Domyślna implementacja metody jest zazwyczaj nieodpowiednia dla nowych klas obiektów. Jeśli chcemy porównywać ze sobą obiekty danej klasy, musimy dla tej klasy utworzyć własną wersję metody equals(), która będzie spełniała następujące warunki:
- musi zwracać wartość true, jeśli porównywne obiekty chcemy traktować jako takie same (...sobie równe);
- musi działać symetrycznie: JEŚLI obj1.equals(obj2) == true, WÓWCZAS obj2.equals(obj1) też musi być true;
- musi być przechodnia: JEŚLI obj1.equals(obj2) oraz obj2.equals(obj3), WÓWCZAS obj1.equals(obj3) musi być true;
- musi zwrócić false, gdy nie-pusty obiekt porównujemy z wartością pustą (null) - czyli obj1.equals(null) == false JEŚLI obj1 != null.
Przykładowa implementacja nadpisanej metody equals():
class Person {
String name;
String familyName;
int PESEL;
...
@Override
public boolean equals( Object obj ) {
if (obj == null) {
return false;
}
if( obj instanceof Person ) { // bez tego może wystąpić ClassCastException
Person comparedPerson = (Person) obj;
return this.name.equals( comparedPerson.name ) &&
this.familyName.equals( comparedPerson.familyName ) &&
this.PESEL == comparedPerson.PESEL;
}
return false;
}
}