Sunday, May 15, 2011

Equals method in java

Object class have methods like equals() and hashcode(). These methods have their own contracts which have to be fulfilled to override them.
Default implementation of equals() in object class
The default implementation of equals() in Object class is based on the == operator: Two objects are equal if and only if they are the same object. Naturally, most classes should define their own alternative implementation of this important method.
Contract of equals method
Implementing equals() correctly is not straightforward. The equals() method has a contract that says the equality relation must meet these demands:
  • It must be reflexive. For any reference x, x.equals(x) must return True.
  • It must be symmetric. For any two nonnull references x and y, x.equals(y) should return the exact same value as y.equals(x).
  • It must be transitive. For any three references x, y, and z, if x.equals(y) and y.equals(z) are True, then x.equals(z) must also return True.
  • It should be consistent. For any two references x and y, x.equals(y) should return the same value if called repeatedly (unless, of course, either x or y were changed between the repeated invocations of equals()).
  • For any nonnull reference x, x.equals(null) should return False.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values x and y, this method returns true if and only if x and y refer to the same object (x==y has the value true).

Note that 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.

Steps to be taken when implementing equals()
  1. Use the == operator to check whether the incoming object is null. Its kind of performance optimization.
    public boolean equals(Object incomingObject) {
      if (incomingObject == null) return false;
    }


  2. Use the == operator to check if the argument is a reference to this object. If so, return true. This is just a performance optimization, but one that is worth doing if the comparison is potentially expensive.

    public boolean equals(Object incomingObject){
        if(this==incomingObject)
            return true;
    }


  3. Use the instanceof operator to check if the argument has the correct type.
    If not, return false. Typically, the correct type is the class in which the method occurs. Occasionally, it is some interface implemented by this class. Use an interface if the class implements an interface that refines the equals contract to permit comparisons across classes that implement the interface. Collection interfaces such as Set, List, Map, and Map.Entry have this property.

    public boolean equals(){
        if (!(incomingObject instanceof MyClass)) return false;
    }

    Note  : I have not checked like this:

    if(incomingObject instanceof MyClass)
      do something;

    The reason being instanceof returns true even when incomingObject is subclass object. So its important to check whether the object is type of class we are writing equals or not. If not, what is the point of writing further logic. Just return false, and leave.

  4. Cast the argument to the correct type. Because this cast was preceded by an instanceof test, it is guaranteed to succeed.

    public boolean equals(Object incomingObject){
      MyClass mc = (MyClass) incomingObject;
    }

  5. For each “significant” field in the class, checks if that field of the argument matches the corresponding field of this object. If all these tests succeed, return true; otherwise, return false
  6. Writing the complete equals function
    Finishing whole steps:

    public boolean equals(Object o) {
      if (o == null) return false;
      if (o == this) return true;
      if (!(o instanceof MyClass)) return false;
      MyClass mc = (MyClass) o;
      return ... // compare members of mc
    }


  7. When you are finished writing your equals method, ask yourself three questions: Is it symmetric? Is it transitive? Is it consistent?

Thanks

No comments:

Post a Comment

Chitika