equals method and == operator in java

A lot of people get confused with the equality operator (==) operator in java. This is typical with programmers with C++ background. Like you might try to compare two Strings with == in java but that will not work as expected.

equals-method-and-equality-operator-in-java

When we compare two reference variables with == operator, it only checks for reference equality. It will return true only if the operands point to the same object (difference between reference and object). == doesn’t check two objects if they are meaningfully equal. Lets take the example of two Strings,

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);

The output of this code will be false. Even though both the variables s1 and s2 refer to String objects with the same value, but == returns false. This is because both String references point to different String objects. == will return true if both s1 and s2 point to the same String object in the heap. The following code will return true as output,

String s1 = new String("hello");
String s2 = s1;
System.out.println(s1 == s2);

The correct way to check if two objects are meaningfully equal is to use the equals method. The java.lang.Object class defines the equals method. It is used to see if two objects are meaningfully equal. So if we modify the first code to use equals method, we’ll get the expected output,

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2));

The above code will result in true as output as one might expect. The String class overrides the equals method of Object class and compare the String objects to see if they contain the same text. So even if s1 and s2 don’t point to the same String object, we got true as the answer.

If we create a class which has instance fields and we think that we might need to check if two objects of our class are meaningfully equal, then we’ll also override the equals method. Lets create a Person class and override the equals method

class Person {
    private long id;
    private String name;
    private int age;
   
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
   
    //other getters and setters
   
    public boolean equals(Object other) {
        //first check if other is an object of Person class
        if(other instanceof Person) {
            Person p = (Person)other;
            //we recognize Person objects by the unique ID, so this is what
            //we'll compare
            if(this.id == other.id) {
                //both objects have same ID
                return true;
            } else {
                //both objects have different ID
                return false;
            }
        } else {
            //other is not of type Person, so we are returning false
            return false;
        }
    }
}

A code which compares two Person objects would look something like this

Person p1 = new Person();
p1.setId(20);
Person p2 = new Person();
p2.setId(20);
System.out.println(p1.equals(p2));

Here we are calling equals method on p1 and passing p2 as argument. Notice the signature of equals method. It takes a parameter of type Object. This allows us to pass any type of object to the equals method. So the first thing we need to check is if the object sent as argument is of type Person or not (by instanceof operator). If it is not, then there is no way the other object is meaningfully equal to the current Person object so we return false. If the object passed as argument is of type Person, then we see if it has the same ID as the object on which the equals method was called. If the IDs are same, then we return true otherwise we return false.

But what happens if we don’t override the equals method? Well the equals method of Object class just does a simple == comparison to check if objects are equal. It looks something like this,

public boolean equals(Object other) {
    if(this == other) {
        return true;
    } else {
        return false;
    }
}

So if you don’t override the equals method yourself, then using == and equals on instances of your class will have same result (Note: this is only applicable if your class doesn’t extend any other class which overrides the equals method).