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.
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 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 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 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
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
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,
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).