Daniel Baechli

Greenhorn
+ Follow
since Dec 19, 2010
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Daniel Baechli

Yes ok thanks for the general info.

I am still having a bit a problem with the example here (not too serious). When looking at it as an isolated code snippet (assuming it compiles fine and no runtime exception ever occcurs) there is simply not enough information to answer the question.

So I just assumed the example on page 583 is referenced. But in this context the proposed hashCode() implementation does not satisfy the hashCode() contract.

If no context is given different answers are possible. Really for demonstration only (I know this makes no sense otherwise!). First the code snippet once again:


In the example below the method labelled as // #1 from the code snippet once is a valid implementation for hashCode() and once not.
The output is in most cases as below (however in rare cases the last line can also be true). Important is only that the first three lines are always true while the last line can be true and false.
true
true
true
false


The code snippet below from Mohamed is interesting but leads to another problem. The proposed equals(Object) method is not valid because it is not reflexive! From the Java API: "It is reflexive: for any non-null reference value x, x.equals(x) should return true."

Output:
Equals method not reflexive

So as the implementation of the equals(Object) method does not fulfill the contract for the equals method the hashCode() method is of no interest - it simply must not apply here.
Chapter 7 - page 585

On top of page 585 two implementations for a hashCode() method are proposed referring to the previous example starting on page 583.


Following questions about these methods are asked on top of page 585:

Time for another pop quiz: Are the preceding two hashCodes legal? Will they successfully retrieve objects from a Map? Which will be faster?


Answer is given on top of page 585 as

The answer to the first two questions is Yes and Yes.



Correct answer should however be:
The answer to the first question is No for the first proposed method and Yes for the second proposed method. (I happily omit the answer to the second question).

Problem is the possible NullPointerException. Important to mention as NPE's are source of many (also serious) errors. The possible NPE is mentioned in several discussions. However I did not find a statement that because of this NPE the proposed method fails to fulfill contract for hashCode().

Code referred to on page 583 is as below (I assume this code is referred as otherwise the examples lack context):


The hashCode() Contract from the Java API is on page 554. The second condition is as below:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.


To "produce the same integer result" in this sense implicitly assumes that the hashCode() method for both objects completes in the case "If two objects are equal according to the equals(Object) method". So in more detail the above can be stated that "If two objects are equal according to the equals(Object) method" the hashCode() method for both objects must complete and the obtained integer result for both methods must be the same.

The code below shows an example where two dog objects are equal but the hashCode() method on any of the objects does not complete. So the contract of the hashCode() method is not fulfilled.

Code sample:

The code above gives the following output:

true
HashCode comparison not possible


In line 21 there is no problem. The two objects dog1 and dog2 are equal regarding the equals(Object) method. There is no problem here. dog2 is an instance of Dog and dog2.name is null as the name field of dog1. So the equals(Object) method yields true.

In line 23 however there is of course a problem. When invoking the hashCode() method to compare the hashCodes on any of the two objects a NullPointerException occurs. The length() method is invoked on the name field which contains a null value for both objects.

So comparison of the hashCodes is not possible as at least one hashCode() method does not complete (in fact both) - so the contract of the hashCode() method is not fulfilled.

The problem here is really that the hashCode() contract requires the hashCod() method to complete on both involved objects if the objects are equal as stated above. It does not say that when one of the methods does not complete the contract is fulfilled – in the contrary in this very case the contract is not fulfilled.

Of course it is easy to add a null check to the proposed method so that the hashCode() contract is fulfilled. I will however not to do so as it only distracts from the actual design (which is that you can have dogs with no names ...).