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)Object class 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.equals method of Object class- equals method precisely states what it requires. Once you understand it completely, implementation becomes relatively easy, moreover it would be correct. Let's understand what each of this really means.equals method to behave otherwise.equals method that has comparison with an object of java.lang.String class, or with any other built-in Java class for that matter. It is very important to understand this requirement properly, because it is quite likely that a naive implementation of equals method may violate this requirement which would result in undesired consequences.equals method in such a way that it provides comparison for objects of class A and class B. Now, if author of class B decides to modify its equals method such that it would also provide equality comparison with class C; he would be violating the transitivity principle. Because, no proper equals comparison mechanism would exist for class A and class C objects.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.public int hashCode()equals method.hashCode method of Object class- hashCode is:
equals method, the contract specified by the hashCode method is relatively simple and easy to understand. It simply states two important requirements that must be met while implementing the hashCode method. The third point of the contract, in fact is the elaboration of the second point. Let's understand what this contract really means.
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.
hashCode counterpart of the requirement specified by the equals method. It simply emphasizes the same relationship - equal objects must produce the same hash code. However, the third point elaborates that unequal objects need not produce distinct hash codes.
equals method, you must override the hashCode method as well. Failing to comply with this requirement usually results in undetermined, undesired behavior of the class when confronted with Java collection classes or any other Java classes.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 and other wrapper classes.
1. public class Test
2. {
3. private int num;
4. private String data;
5.
6. public boolean equals(Object obj)
7. {
8. if(this == obj)
9. return true;
10. if((obj == null) || (obj.getClass() != this.getClass()))
11. return false;
12. // object must be Test at this point
13. Test test = (Test)obj;
14. return num == test.num &&
15. (data == test.data || (data != null && data.equals(test.data)));
16. }
17.
18. public int hashCode()
19. {
20. int hash = 7;
21. hash = 31 * hash + num;
22. hash = 31 * hash + (null == data ? 0 : data.hashCode());
23. return hash;
24. }
25.
26. // other methods
27. }
num and data. These two variables define state of the object and they also participate in the equals comparison for the objects of this class. Hence, they should also be involved in calculating the hash codes of this class objects.equals method first. We can see that at line 8, the passed object reference is compared with this object itself, this approach usually saves time if both the object references are referring to the same object on the heap and if the equals comparison is expensive. Next, the if condition at line 10 first checks if the argument is null, if not, then (due to the short-circuit nature of the OR || operator) it checks if the argument is of type Test by comparing the classes of the argument and this object. This is done by invoking the getClass() method on both the references. If either of these conditions fails, then false is returned. This is done by the following code -if((obj == null) || (obj.getClass() != this.getClass())) return false; // preferif(!(obj instanceof Test)) return false; // avoidfalse if the argument is a subclass of the class Test. However, in case of the second condition (code in red) it fails. The instanceof operator condition fails to return false if the argument is a subclass of the class Test. Thus, it might violate the symmetry requirement of the contract. The instanceof check is correct only if the class is final, so that no subclass would exist. The first condition will work for both, final and non-final classes. Note that, both these conditions will return false if the argument is null. The instanceof operator returns false if the left hand side (LHS) operand is null, irrespective of the operand on the right hand side (RHS) as specified by JLS 15.20.2. However, the first condition should be preferred for better type checking.equals method in such a way that it provides equals comparison only for the objects of the same class. Note that, this is not mandatory. But, if a class decides to provide equals comparison for other class objects, then the other class (or classes) must also agree to provide the same for this class so as to fulfill the symmetry and reflexivity requirements of the contract. This particular equals method implementation does not violate both these requirements. The lines 14 and 15 actually perform the equality comparison for the data members, and return true if they are equal. Line 15 also ensures that invoking the equals method on String variable data will not result in a NullPointerException.equals method, primitives can be compared directly with an equality operator (==) after performing any necessary conversions (Such as float to Float.floatToIntBits or double to Double.doubleToLongBits). Whereas, object references can be compared by invoking their equals method recursively. You also need to ensure that invoking the equals method on these object references does not result in a NullPointerException.equals method correctly.== operator to check if the argument is the reference to this object, if yes. return true. This saves time when actual comparison is costly.null and it is of the correct type, if not then return false.if((obj == null) || (obj.getClass() != this.getClass())) return false;ClassCastException.==) after performing any necessary conversions (Such as float to Float.floatToIntBits or double to Double.doubleToLongBits). Whereas, object references can be compared by invoking their equals method recursively. You also need to ensure that invoking equals method on these object references does not result in a NullPointerException, as shown in the example above (Line 15).equals method. Only you can decide which class members are significant and which are not.equals method. It takes a java.lang.Object as an argument, do not use your own class instead. If you do that,
you will not be overriding the equals method, but you will be overloading it instead; which would cause problems. It is a very common mistake, and since it does not result in a compile time error, it becomes quite difficult to figure out why the code is not working properly.equals method to verify that it fulfills all the requirements stated by the general contract of the equals method.hashCode method whenever you override the equals method, that's unpardonable. ;)hashCode method of this example. At line 20, a non-zero constant value 7 (arbitrary) is assigned to an int variable hash. Since the class members/variables num and data do participate in the equals method comparison, they should also be involved in the calculation of the hash code. Though, this is not mandatory. You can use subset of the variables that participate in the equals method comparison to improve performance of the hashCode method. Performance of the hashCode method indeed is very important. But, you have to be very careful while selecting the subset. The subset should include those variables which are most likely to have the greatest diversity of the values. Sometimes, using all the variables that participate in the equals method comparison for calculating the hash code makes more sense.hashCode method on the variable data does not result in a NullPointerException if data is null. This implementation ensures that the general contract of the hashCode method is not violated. This implementation will return consistent hash code values for different invocations and will also ensure that equal objects will have equal hash codes.hashCode method, primitives can be used directly in the calculation of the hash code value after performing any necessary conversions, such as float to Float.floatToIntBits or double to Double.doubleToLongBits. Since return type of the hashCode method is int, long values must to be converted to the integer values. As for hash codes of the object references, they should be calculated by invoking their hashCode method recursively. You also need to ensure that invoking the hashCode method on these object references does not result in a NullPointerException.hashCode method which calculates hash code values such that the distribution is uniform is not a trivial task and may require inputs from mathematicians and theoretical computer scientist. Nevertheless, it is possible to write a decent and correct implementation by following few simple rules.hashCode method correctly.int variable, called hash.int var_code for each variable var as follows -
(var) is byte, char, short or int, then var_code = (int)var;(var) is long, then var_code = (int)(var ^ (var >>> 32));(var) is float, then var_code = Float.floatToIntBits(var);(var) is double, then -long bits = Double.doubleToLongBits(var);
var_code = (int)(bits ^ (bits >>> 32));(var) is boolean, then var_code = var ? 1 : 0;(var) is an object reference, then check if it is null, if yes then var_code = 0; otherwise invoke the hashCode method recursively on this object reference to get the hash code. This can be simplified and given as -var_code = (null == var ? 0 : var.hashCode());var_code in the original hash code hash as follows - hash = 31 * hash + var_code;hash.hashCode method and check if it is returning equal hash codes for equal objects. Also, verify that the hash codes returned for the object are consistently the same for multiple invocations during the same execution.equals and hashCode methods are merely useful as guidelines, these are not absolute laws or rules. Nevertheless, following them while implementing these two methods will certainly give you correct and consistent results. equals method provides "deep comparison" by checking if two objects are logically equal as opposed to the "shallow comparison" provided by the equality operator ==.equals method in java.lang.Object class only provides "shallow comparison", same as provided by the equality operator ==.equals method only takes Java objects as an argument, and not primitives; passing primitives will result in a compile time error.equals method will never result in a compile time error or runtime error.java.lang.String, if the equals argument type (class) is different from the type of the object on which the equals method is invoked, it will return false.java.lang.StringBuffer does not override the equals method, and hence it inherits the implementation from java.lang.Object class.equals method must not provide equality comparison with any built in Java class, as it would result in the violation of the symmetry requirement stated in the general contract of the equals method.null is passed as an argument to the equals method, it will return false.return 1; is a legal implementation of the hashCode method, however it is a very bad implementation. It is legal because it ensures that equal objects will have equal hash codes, it also ensures that the hash code returned will be consistent for multiple invocations during the same execution. Thus, it does not violate the general contract of the hashCode method. It is a bad implementation because it returns same hash code for all the objects. This explanation applies to all implementations of the hashCode method which return same constant integer value for all the objects.java.lang.Short, java.lang.Byte, java.lang.Character and java.lang.Integer simply return the value they represent as the hash code by typecasting it to an int.java.lang.String caches its hash code, i.e. it calculates the hash code only once and stores it in an instance variable and returns this value whenever the hashCode method is called. It is legal because java.lang.String represents an immutable string.
java.lang.Object class. The general contract of these two methods is available here.pdf format. This chapter deals with all the methods of java.lang.Object class. It also discusses in details the implementation of equals and hashCode methods, correct and incorrect way of overriding them etc. This article is partially based on the information given in this book.equals and hashCode - This FAQ question discusses the importance of overriding equals and hashCode methods correctly. It also discusses important issues regarding these two methods with respect to Java collection framework.equals and hashCode methods.
instanceof condition in the equals method. If you notice any ambiguity, error in the article and/or the mock test, please do let me know. Your feedback is very important in making this article and test more useful.Author: Manish Hatwalne