Tuesday, June 4, 2013

Difference between equals() and == in Java?


What’s the difference between equals() and ==?

Before discussing the difference between “==” and the equals() method, it’s important to understand that an object has both a location in memory and a specific state depending on the values that are inside the object.

The “==” operator

In Java, when the “==” operator is used to compare 2 objects, it checks to see if the objects refer to the same place in memory. In other words, it checks to see if the 2 object names are basically references to the same memory location. A very simple example will help clarify this:
String obj1 = new String("xyz");

String obj2 = new String("xyz");

if(obj1 == obj2)
   System.out.println("obj1==obj2 is TRUE");
else
  System.out.println("obj1==obj2 is FALSE");
    

Take a guess at what the code above will output. Did you guess that it will outputobj1==obj2 is TRUE? Well, if you did, then you are actually wrong. Even though the strings have the same exact characters (“xyz”), The code above will actually output:
 obj1==obj2 is FALSE

The “==” operator compares the objects’ location(s) in memory

Are you confused? Well, let us explain further: as we mentioned earlier, the “==” operator is actually checking to see if the string objects (obj1 and obj2) refer to the exact same memory location. In other words, if both obj1 and obj2 are just different names for the same object then the “==” operator will return true when comparing the 2 objects. Another example will help clarify this:
String obj1 = new String("xyz");

// now obj2 and obj1 reference the same place in memory
String obj2 = obj1;

if(obj1 == obj2)
   System.out.printlln("obj1==obj2 is TRUE");
else
  System.out.println("obj1==obj2 is FALSE");

Note in the code above that obj2 and obj1 both reference the same place in memory because of this line: “String obj2 = obj1;”. And because the “==” compares the memory reference for each object, it will return true. And, the output of the code above will be:
obj1==obj2 is TRUE

The equals() method

Now that we’ve gone over the “==” operator, let’s discuss the equals() method and how that compares to the “==” operator. The equals method is defined in the Object class, from which every class is either a direct or indirect descendant. By default, the equals() method actually behaves the same as the “==” operator – meaning it checks to see if both objects reference the same place in memory. But, the equals method is actually meant to compare the contents of 2 objects, and not their location in memory.
so, how is that behavior actually accomplished? Simple – the equals class is overridden to get the desired functionality whereby the object contents are compared instead of the object locations. This is the Java best practice for overriding the equals method – you should compare the values inside the object to determine equality. What value you compare is pretty much up to you. This is important to understand – so we will repeat it: by default equals() will behave the same as the “==” operator and compare object locations. But, when overriding the equals() method, you should compare the values of the object instead.

An example of the equals() method being overriden
The Java String class actually overrides the default equals() implementation in the Object class – and it overrides the method so that it checks only the values of the strings, not their locations in memory. This means that if you call the equals() method to compare 2 String objects, then as long as the actual sequence of characters is equal, both objects are considered equal. Here is an example that will help clarify this:
String obj1 = new String("xyz");

String obj2 = new String("xyz");

if(obj1.equals(obj2))
   System.out.printlln("obj1==obj2 is TRUE");
else
  System.out.println("obj1==obj2 is FALSE");


This code will output the following:
obj1==obj2 is TRUE
As we discussed, Java’s String class overrides the equals() method to compare the characters in a string. This means that the comparison between the 2 String objects returns true since they both hold the string “xyz”. It should now be clear what the difference is between the equals() method and the “==” operator.

Other example is:
StringBuffer s1 = new StringBuffer("kondal");
StringBuffer s2 = new StringBuffer("kondal");
System.out.println(s3.equals(s4));  //false

Above comparison results 'false' because of StringBuffer has not overridden equals() method as like String class.So, equals() comparison on StringBuffer same as '==' comparison, since it looks for Object 'equals()' method.

String s3 = "kondal";
Now, System.out.println(s3.equals(s1));  //false

Above code also returns false,since 'equals() method in String class has the following criteria.

  public boolean equals(Object anObject) {
if (this == anObject) {
   return true;
}
if (anObject instanceof String) { // Here it fails, StringBuffer is not a instance of String class
   String anotherString = (String)anObject;
   int n = count;
   if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
   if (v1[i++] != v2[j++])
return false;
}
return true;
   }
}
return false;

    }


The following contracts should be satisfied while overriding 'equals() method.

It is reflexive: for any non-null reference value x, x.equals(x) should return true. 
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. 
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. 
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. 
For any non-null reference value x, x.equals(null) should return false. 

It is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes, but vice-versa may not be true

No comments:

Post a Comment