8

How do I override the equals method in the object class?

i.e I have

class Person{

//need to override here
public boolean equals (Object obj){

}

I want to convert the parameter obj to a type Person, but if I do (Person) obj it won't work.

user69514
  • 26,935
  • 59
  • 154
  • 188
  • 1
    Note you need to be careful if you have a non-final class. Typically you should check the runtime class with `obj.getClass() == Person` rather than `instanceof Person`. Although it is possible to write a contract that makes derived types equal (like `java.util.List`). Also you should override `hashCode` if you override `equals`, but that's probably getting ahead a bit. – Tom Hawtin - tackline Feb 23 '10 at 05:33

9 Answers9

10

It's actually more complicated than you might think. Have Eclipse (or whatever IDE you're using) auto-generate an equals method; you'll see it contains a few checks and casts before it does a comparison.

Also see here: http://www.javapractices.com/topic/TopicAction.do?Id=17

Dan Passaro
  • 4,211
  • 2
  • 29
  • 33
9

You can cast it inside the method, just make sure that is of the right type using instance of

if(obj instanceof Person)
{
   Person otherPerson = (Person) obj;
   //Rest of the code to check equality
}
else
{
//return false maybe
}
pgmura
  • 708
  • 5
  • 16
8
@Override
public boolean equals(Object o) 
{
    if (o instanceof Person) 
    {
      Person c = (Person) o;
      if ( this.FIELD.equals(c.FIELD) ) //whatever here
         return true;
    }
    return false;
}
twodayslate
  • 2,803
  • 3
  • 27
  • 43
5

Take a look at Regarding Object Comparison.

Be aware that if you override equals() you must also override hashCode(). The equals/hashCode contract is that if two objects are equal they must have the same hash code.

Community
  • 1
  • 1
cletus
  • 616,129
  • 168
  • 910
  • 942
3

If you plan to create subclasses of Person, use something like

if(obj!=null && obj.getClass() == Person.class)

rather than instanceof

saugata
  • 2,823
  • 1
  • 27
  • 39
  • Why would one use getClass() instead of instanceof? (Just curious.) – Tom Feb 23 '10 at 05:27
  • 2
    e.g. if Employee extends Person ; and Employee has additional fields like id etc. You may get a false positive using person.equals(employee) – saugata Feb 23 '10 at 11:05
  • 1
    It's not so much the false positives you need to worry about, but the **violation of reflexivity**. Regardless of what you use, you can basically guarantee that `new Employee().equals(new Person())` is going to be false (Person is not an instance of Employee). The result **must** be the same if you invert the arguments, so a Person **cannot** be equal to a subclass of itself (unless you do something very funky in the subclass' `equals()` method). – Andrzej Doyle Feb 24 '10 at 12:28
  • 2
    Additionally - I would prefer the example to read `if(obj!=null && obj.getClass() == this.getClass())` as this will work properly when inherited by subclasses. The example in your answer at the moment would lead to an instance of a subclass not being equal to itself (unless it overrode equals()), which is also wrong. – Andrzej Doyle Feb 24 '10 at 12:29
2

The only reason to use getClass() rather than instanceof is if one wanted to assert that both references being compared point to objects of the exact same class rather than objects implementing the same base class.

Say we have an Employee e and a Manager m (extends Employee).

m instanceof Employee would yield true, m.getClass() == Employee.class would return false.

In some cases the latter might be preferred, but rarely in case of comparison of instances in equals() or hashCode() methods.

Sufian
  • 6,405
  • 16
  • 66
  • 120
jwenting
  • 5,505
  • 2
  • 25
  • 30
1

I prefer the simpler, null-safe(r) Objects.equals for any field type:

@Override
public boolean equals(Object o) {
    if (o instanceof Person) {
        Person p = (Person) o;
        return Objects.equals(p.FIELD, this.FIELD);
    }
    return false;
}
wrapperapps
  • 937
  • 2
  • 18
  • 30
0

One more point may be good to know that after you override equals() method (and also hashcode()) method you can to compare two objects of same class like follows:

Person p1 = new Person();
Person p2 = new Person();

....

if ( p1.equals( p2 ) )

{
   // --- Two Persons are equal, w.r.t the fields you specified in equals method ---

}
Sufian
  • 6,405
  • 16
  • 66
  • 120
lucentmind
  • 192
  • 2
  • 11
0

I know this is answered, but in my travels I have found this the most efficient way to override the comparison of an object to make sure it happens the same globally:

@Override
public boolean equals(Object o) {
    return o instanceof Person && this.getSomeMagicalField().equals(((Person) o).getSomeMagicalField());
}

or if you are not comparing strings:

@Override
public boolean equals(Object o) {
    return o instanceof Person && this.getSomeMagicalField() == (Person) o).getSomeMagicalField();
}
Chad Bingham
  • 32,650
  • 19
  • 86
  • 115