Option 2 is correct because hashCode() for all the multiples of 3 is 0. Therefore, if we return true in the equals() method for all the multiples of 3, the condition will be met. It also returns true if the object is compared with itself.
Well, I must say, this is a terrible explanation in favour of why that option works. Probably because, equals()
and hashCode()
method themselves have a terrible implementation. Currrently, the equals()
method returns true, if the two objects have the same hashcodes (In a way). Let's take a look at that part again:
return this == obj? true : (theval%3 == 0 && ((GoodOne)obj).theval%3==0) ? true :false;
First of all, that expression can be improved to (although this is also not a good implementation):
return this == obj? true : theval % 3 == ((GoodOne)obj).theval % 3;
Now theVal % 3
is nothing but the hashcodes of that object. So, basically, this method is judging two objects equals based on their hashcodes. (Well, the hashCode()
method isn't also an example of good implementation).
One big issue with the equals()
method is, it doesn't handle null
. My God. I suggest stop reading from that resource, what do you name it - Enthuware.
Having said that, this equals method would work fine in collaboration with the given hashcode (Provided, null
is handled properly). How, let's consider the contract of equals
method:
- Reflexive: That is fine.
a.theVal % 3 == a.theVal % 3
. - Symmetric: This is also fine. For two objects
a
andb
, ifa.theVal % 3 == b.theVal % 3
, then the reverse is also true. - Transitive - This is also fine.
a.theVal % 3 = b.theVal % 3
andb.theVal % 3 == c.theVal % 3
, implies thata.theVal % 3 == c.theVal % 3
. - Consistent - Well, if
a.theVal % 3 == b.theVal % 3
, then that will be true always, provided neither ofa.theval
orb.theVal
has changed.
Now comes the contract between equals()
and hashCode()
:
- If two objects are equals, then their hashCodes must be equal. That is certainly true here, since you are already judging objects equals based on hashcodes.
So, this explains how the 2nd option is fine here.
Something you should really keep in mind:
One general point, which is very important, to remember is, you should use the same set of object attributes to calculate the hashcodes that you use to judge the object equals, else the contract will break.
For e.g, if you have one more field in your class say - name
, and your hashCode
method is changed to:
theVal % 3 * name.hashCode();
but you didn't change the equals()
method. Then if two objects have same theVal
value, but different name, they will be equal as per the equals()
method implementation, but their hashcodes will be different given the above implementation of hashCode()
.
Better equals() and hashCode()?
I said that, the given hashCode()
and equals()
method is not a very good implementation. Then what can be considered a somewhat good implementation. Well, I suggest you to go through Effective Java - Item 9, that really goes deep in this topic.
If you are using Eclipse IDE, then you can ask it to generate those two methods. Eclipse generates quite a good implementation of equals()
and hashCode()
methods.