DEV Community

André Jacques
André Jacques

Posted on • Edited on

Java Override Equals Override `equals` method in Java

The == operator is a false friend in Java. It works properly only on primitive and will make you cry if you used it on any other referenced Object, for the most part.

The basic

As a rule of thumb, every equals method should start like this:

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (!(obj instance ClassName)) {
            return false;
        }

        // custom logic here
    }
Enter fullscreen mode Exit fullscreen mode

The ClassName should be replaced by whatever type your class is. After that, I usually apply one of the following solutions.

The class as only one relevant field

In the case that the class has only one relevant field, I will return automatically either the == operation (for primitive) or the equals of the field.


public class Person

    private String fullname;

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (!(obj instance Person)) {
            return false;
        }

        Person converted = (Person)obj;

        return this.fullname.equals(converted.fullname);
    }

}
Enter fullscreen mode Exit fullscreen mode

The class as many relevant fields

I usually have two options here.

The toString() contains all the relevant field

There is no need to add complexity in a class if something can help you with your code. There is no need to test for instanceof since toString is defined everywhere, and no need to cast for the same reason.


public class Person

    private String firstname;
    private String lastname;

    @Override
    public String toString() {
        return this.firstname + " " + this.lastname;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        return this.toString().equals(obj.toString());
    }

}
Enter fullscreen mode Exit fullscreen mode

It is not mandatory to be the toString. Sometimes other methods do the same job. You need to keep in mind that other methods will require to test for and cast the object before comparing.

There is no method to help

In that situation, I will usually cascade if until the last relevant field.


public class Person

    private String firstname;
    private String lastname;
    private Date dob;

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (!(obj instance Person)) {
            return false;
        }

        Person converted = (Person)obj;

        if (!(this.firstname.equals(converted.firstname)) {
            return false;
        }

        if (!(this.lastname.equals(converted.lastname)) {
            return false;
        }

        return this.dob.equals(converted.dob);
    }

}
Enter fullscreen mode Exit fullscreen mode

I know that I could probably do something like this:

    return this.firstname.equals(converted.firstname) && this.lastname.equals(converted.lastname) && this.dob.equals(converted.dob);
Enter fullscreen mode Exit fullscreen mode

I don't really like this because it is mainly hard to read. I know that Java will probably optimize the bytecode with these kinds of statement, nevertheless, I believe that in most cases, it won't really matter.

Don't forget that, to be able to use HashMap and stuff, you also need to override the hashcode. Here are the main rules:

  • If 2 instances are equal, then both hashcode MUST BE equal;
  • If 2 instances are not equal, then both hashcode SHOULD NOT BE equal.

A good hashcode algorithm that lives up to the second rule will make the use of HashMap and HashSet more efficient.

Top comments (1)

Collapse
 
andreidbr profile image
Andrei Dobra

Really nice and simple, I really like how you presented your chain of thought. Thanks for this :)