The equals method and the == operator are often the focus of tests and interview questions as testing for equality in Java is often something that can trip up beginner java developers. So what is the difference between the method and the operator? Lets try and make this crystal clear.
Both the equals() method and the == comparison operator check for equality, but they achieve it in different ways, which is where some people get confused.
The == Operator
The == operator compares the value of two objects or primitives, but work differently depending on which you are comparing. This binary operation only has two results, either “true” or “false”, so the operands are either equal or they are not equal.
Comparing Primitives With The == Operator
If you are using the == operator to compare two primitives, they are compared based on the value of the primitives. So 1 will never be equal to 2, and 1 will always be equal to 1.
Lets see the == operators in java with an example program. The unit test below is to demonstrate how the == operator works on primitive values. As you can see the result is the primitives are equal if they have the same value, or not equal if they have different values.
1 2 3 4 5 6 7 8 9 10 11 12 |
@Test public void equalsOperatorPrimitivesTest() { int a = 1; int b = 1; int c = 2; assertThat("Same primitive value is equal", a == b, is(true)); assertThat("Different primitive value is different", a == c, is(false)); } |
Comparing Objects With The == Operator
If you are using the == operator for comparing objects in java, they are compared based on the object references, so comparing if both operands are referring to the same object.
If we use Strings as examples and comparing strings in java to show the behaviour of the == operator with objects, we can say that == will only return true if 2 string variables are pointing to the same object. Lets show this with a junit test to confirm. If we create strings using the “new” opcode it guarantees that we get new objects each time. We run this unit test “a” is not equal to “b” as although they have the same value, they are different String objects as we have used the new String() to ensure that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@Test public void equalsOperatorObjectsTestStrings() { String a = new String("a"); String b = new String("a"); String c = new String("c"); assertThat("Same object value is not equal", a == b, is(false)); assertThat("Different object value is not equal", a == c, is(false)); System.out.println(a == b); System.out.println(a == c); } |
With the result that both objects show as false for equality as they are all new objects with unique references, irrespective of the values within them
1 2 |
false false |
If we do similar with String literals we get a different result. When you create a string using a literal, the java virtual machine looks up the literal in its poolof string objects. If your literal already exists in the pool, then a reference to the existing String object will be returned rather than a new one. A new reference is only returned in your literal doesnt already exist in the internal pool.
So when we run our unit test to check for equality with literals, if the literals have the same value they will return true for an equality check with the == operator.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Test public void equalsOperatorObjectsTestLiterals() { String a = "a"; String b = "a"; String c = "c"; assertThat("Same object is equal", a == b, is(true)); assertThat("Different object is different", a == c, is(false)); System.out.println(a == b); System.out.println(a == c); } |
So strings “a” and “b” come back as equal as they have the same value.
1 2 3 |
true false |
In languages like C++ you can use operator overloading to modify the behavior or operators. In java we dont have operator overloading, so we can be assured that the == operator can only work in the ways we have described above.
Another thing to mention is that autoboxing has changed the rules slightly, as the == method also changes how things work there also. But we will save autoboxing for another time.
The equals() Method
The equals() method in Java can be used to check both identity and equality. What we mean here is that the equals() method has a default behavior as it is a method on java.lang.Object. The default behaviour is to check for identity by confirming if the two objects have the same object references.
But this is only the case when its used for its default behavior, as this method can be overridden so it could in theory work in an entirely different way or perform some additional logic when performing a comparison of objects and testing for equality for example.
For instance you may have create your own classes of animal, and define that you animal is only equal if a comparison indicates that the value “species” is the same. So if you had an animal with species “Dog” and an animal with species cat, your equals method for your Animal object could return false as they are different species.