Java super class java.lang.Object has two very important methods defined in it. They are –
- public boolean equals(Object obj)
- public int hashCode()
public boolean equals(Object obj)
This method checks if some other object passed to it as an argument is equal to the object on which this method is invoked. The default implementation of this method in Object class, which simply checks if two object references x and y refer to the same object. i.e. It checks if x == y. This particular comparison is also known as “Shallow Comparison”. However, the classes providing their own implementations of the equals method are supposed to perform a “Deep Comparison”; by actually comparing the relevant data members. Since Object class has no data members that define its state, it simply performs shallow comparison. The contract of the equals method precisely states what it requires.
- Reflexive – It simply means that the object must be equal to itself, which it would be at any given instance; unless you intentionally override the equals method to behave otherwise.
- Symmetric – It means that if object of one class is equal to another class object, the other class object must be equal to this class object. In other words, one object can not unilaterally decide whether it is equal to another object; two objects, and consequently the classes to which they belong, must bilaterally decide if they are equal or not. They BOTH must agree.
- Transitive – It means that if the first object is equal to the second object and the second object is equal to the third object; then the first object is equal to the third object.
- Consistent – It means that if two objects are equal, they must remain equal as long as they are not modified. Likewise, if they are not equal, they must remain non-equal as long as they are not modified. The modification may take place in any one of them or in both of them.
- null comparison – It means that any instantiable class object is not equal to null, hence the equals method must return false if a null is passed to it as an argument. You have to ensure that your implementation of the equals method returns false if a null is passed to it as an argument.
- Equals & Hash Code relationship – It means that if two objects are equal, then they must have the same hash code, however the opposite is NOT true.
public int hashCode()
This method returns the hash code value for the object on which this method is invoked. This method returns the hash code value as an integer and is supported for the benefit of hashing based collection classes such as Hashtable, HashMap, HashSet etc. This method must be overridden in every class that overrides the equals() method. Contract specified by the hashCode() method are :-
- Consistency during same execution – Hash code returned by the hashCode() method must be consistently the same for multiple invocations during the same execution of the application as long as the object is not modified to affect the equals() method.
- Hash Code & Equals relationship – It simply emphasizes the same relationship – equal objects must produce the same hash code. However unequal objects need not produce distinct hash codes.
Implementation Example
The following code exemplifies how all the requirements of equals() and hashCode() methods should be fulfilled so that the class behaves correctly and consistently with other Java classes. This class implements the equals method in such a way that it only provides equality comparison for the objects of the same class, similar to built-in Java classes like String class.
public class Test { private int num; private String data; public boolean equals(Object obj) { if(this == obj) return true; if((obj == null) || (obj.getClass() != this.getClass())) return false; // Object must be Test at this point Test test = (Test)obj; return num == test.num && (data == test.data || (data != null && data.equals(test.data))); } public int hashCode() { int hash = 7; hash = 31 * hash + num; hash = 31 * hash + (null == data ? 0 : data.hashCode()); return hash; } }
Now, let’s examine the hashCode() method of this example. A non-zero constant value 7 (arbitrary) is assigned to an int variable hash. Since the class members/variables num and data participate in the equals method comparison, they should also be involved in the calculation of the hash code.