Java and J2EE Tutorials, Jsp and Servlet Tutorials, Spring MVC, Solr, XML, JSON Examples, Hibernate & Struts 2 Hello World projects



Sunday, 16 February 2014

How to override equals() in Java - Example

In our previous discussions we came across a quick introduction to Java’s Collection API and Implementation classes for List, Set and Map interface. In this particular blog we will discuss about a very useful topic i.e. "Why to override equals() in Java" and "How to override equals in Java".

We all know it very well that all classes in Java are descendent of Object class, or we can say every class inherits the methods and properties of Object class by default. There are a number of methods in Object class and hence is "public boolean equals(){}".

The public boolean equals(){}, compares two objects and return true or false accordingly. If we don’t override equals in our own class than one present in Object class is called and it compares the object using ‘==’ operator and hence two objects are equal only if their references are same.

Assume we have an class Apple, lets compare its objects using equals() and examine the result.
class Apple {

 private int id;
 private String name;

 public Apple() {
 }

 public Apple(int id, String name) {
  this.id = id;
  this.name = name;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
}


No lets see what happened when we call an equals() method from Object class itself without overriding it.
public class Implementation {
 public static void main(String args[]) {
  Apple greenApple = new Apple(1, "Apple");
  Apple redApple = new Apple(1, "Apple");

  // returns a false
  System.out.println(greenApple.equals(redApple));
 }
}
In the example above we can see that even if two instance of Apple are having same data in them but the equals() method from Object class is assuming them to be non equal. The reason is the default implementation of equals() check for references and two objects are same only if their reference is same. And certainly you would not want this kind of behavior in your application, hence we override equals.
Note: Two String object with same values returns true on equals() even if having different references, the reason is String itself override equals() and implement the functionally so that the String content to compare not their references. Hence we can do it in our very own class.

We can override equals() in our own class and give that our own implementation to compare objects considering some contract. The meaning of contract here is that when overriding equals() we must took care of certain rules and those rules should not violate.

If an class “Apple” has three instances “greenApple” , “redApple” and “yellowApple” than according to contract

1) greenApple.equals(greenApple) must be true always. Reflexive

2) If greenApple.equals(redApple) is true than redApple.equals(greenApple) must be true. Symmetric

3) If greenApple.equals(redApple) is true and redApple.equals(yellowApple) is also true than greenApple.equals(yellowApple) must be true. Transitive

4) For any two refrences say “redApple” and “yellowApple” the equals() method must return true or false consistently unill and unless the property of class that is used is equals() is not modified. Consistent

5) For any non-null reference value greenApple, greenApple.equals(null) should return false. Null Test



Lets now look at our modified version of Apple with an override equals() method.
class Apple {

 private int id;
 private String name;

 public Apple() {
 }

 public Apple(int id, String name) {
  this.id = id;
  this.name = name;
 }

 /*
  * One can use his own logic here unless the contract is being followed.
  */
 public boolean equals(Object o) {
  if (o instanceof Apple && ((Apple) o).getName() == name
    && ((Apple) o).getId() == id)
   return true;
  else
   return false;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
}


Now let’s check if we did it right and does not violate the contract.
public class Implementation {
 public static void main(String args[]) {
  Apple greenApple = new Apple(1, "Apple");
  Apple redApple = new Apple(1, "Apple");
  Apple yellowApple = new Apple(1, "Apple");

  // Reflexive Test : true
  System.out.println("Reflexive Test : " + greenApple.equals(greenApple));

  // Symmetric Test : true
  if (greenApple.equals(redApple)) {
   System.out.println("Symmetric Test : "
     + redApple.equals(greenApple));
  }

  // Transitive Test : true
  if (greenApple.equals(redApple) && redApple.equals(yellowApple)) {
   System.out.println("Transitive Test : "
     + yellowApple.equals(greenApple));
  }

  // Null Test : false
  if (greenApple != null) {
   System.out.println("Null Test : " + greenApple.equals(null));

  }
 }
}


And we are getting the expected result that passes the equals() override contract. Now the conclusion of the whole story is that:

1) The public boolean equals(){} is a method that resides in Object class and hence can be overridden in our own classes as well.

2) If one does not override it than the default behavior is being calles i.e. two objects are equal only if their references are same.

3) We can override equals() in our own class and can give own implementation to compare two objects until and unless we are not violating the equals() contract.

Big Big NOTE: If you override equals() in your own class than you must override hashCode() as well, unless it can violate hashCode() contract with equals() that results in Hash Based collections functionality and implementation.


In this particular blog we came across "why to override equals() in Java" and "How to override equals in Java". In our upcoming blog we will come across "how to override hashCode() in Java" and other tips and tricks about Java.








Thanks for reading !
Being Java Guys Team




1 comment:

  1. Do I also need to override the hashcode method?

    ReplyDelete

Like Us on Facebook


Like Us On Google+



Contact

Email: neel4soft@gmail.com
Skype: neel4soft