• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Paul Clapham
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Roland Mueller
  • Piet Souris
Bartenders:

Discussing errata for K&B, SCJP 6, page 585, hashCode() not valid

 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ...).




 
Bartender
Posts: 3225
34
IntelliJ IDE Oracle Spring Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think instead of using

this can be used

And this would detect the NullPointerException.
 
author
Posts: 9050
21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As a general note, the questions on the real exam assume that the code that you don't see is correct. The exception to this rule is that if you see a code listing that starts at line 1, then you can assume that you're seeing all the code. If a code listing starts at a higher line number, (or doesn't have any line numbers), then assume that the code you don't see is valid.

This assumption should be used when looking at mock questions and exam prep code snippets in general.

I'm not 100% sure that this generalization totally answers your question, but you should make sure that any discussions you have here keep that generalization in mind.

hth,

Bert
 
Daniel Baechli
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic