If a class does not implement the 'equals' and 'hashcode' methods, the default implementation which inherited from the Object class will be used.
equals:
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null 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). can be called as reference equality.The default implementation is something like below,
public boolean equals(Object object) { return this == object; }
hashCode:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
The default implementation is something like below,
public int hashCode() { return VMMemoryManager.getIdentityHashCode(this); }Consider the sample class Dog.
class Dog{ String name; int age; public Dog(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Let's initialize some objects from it.
Dog d1 = new Dog("tim",10); Dog d2 = new Dog("tim",10); Dog d3 = d1; // point it to the d1, so d3 will be referencing to the same object as d1. if(d1.equals(d2)){ System.out.println("yes"); }else{ System.out.println("no"); } /* this code block will print 'no' since d1 and d2 are not pointing to the same object, though we feel like both should be equal since attributes of that object are the same. */ if(d3.equals(d1)){ System.out.println("yes"); }else{ System.out.println("no"); } // prints 'yes' because d3 and d1 are pointing to the same object.So what will happen when using collections framework,
HashMapmap = new HashMap<>(); map.put(d1, "dog1"); map.put(d2, "dog2"); map.put(d3, "dog3"); System.out.println(map.size()); // prints '2' because d1 and d3 are considered as a single object since equals method will verify them as the same object System.out.println(map.get(d2)); // prints 'dog2' System.out.println(map.get(new Dog("tim",10))); // prints 'null' /* 'new Dog("tim",10)' has a new reference, it's a newly created object, though it has the attributes same as the other Dog instances. Since it's reference is different we can't use it as a Key in the map. If we want to retreat a value, we need that exact object we set as key. so when using the collections we need to overide the equals and hashcode methods properly*/
As we can see default equals method implementation provides 'reference equality'. But most of the cases we would normally override equals to implement "value equality" - where two distinct objects are deemed equal, usually by virtue of having equal field values themselves. The exact meaning of equality will depend on the design - the two objects could still be distinguishable in other ways, for example.
If you override equals, you should also override hashCode to be consistent with equals, such that if a.equals(b) is true, then a.hashCode() == b.hashCode(). This will allow instances of your class to be used as keys in hash-based collections (e.g. HashMap) so that you can look up a value, based on a key which is EQUAL to the original one(not the original one), rather than having to use a reference to the exact original key object.
0 comments:
Post a Comment