More Contracts
In the previous installment of this series, we walked through a contract for equality in order to ensure that we had supplied a correct definition for equals. Going back to the Java API documentation for equals on Object, we find this paragraph:
Note that it is generally necessary to override the hashCode method whenever [equals] is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Looking at hashCode, it has its own three conditions that we must satisfy:
- First, it must be consistent, returning the same value for a given object over multiple calls, as long as no underlying information used for equals comparisons has changed. This value can differ from application execution to execution.
- The second condition is already stated above, as part of the equals method documentation: Two objects that return true from an equals comparison must return the same hashCode.
- Finally, two unequal objects can return equivalent hash codes. However, the documentation suggests that this can result in poor performance. We’ll revisit that thought in a little while, once we’ve ensured that Card adheres to the contract for hashCode.
Let’s express the first condition in a test on CardTest, as shown in Listing 2.
Listing 2 Testing for consistency on CardTest.
public void testHashCode() { Card card = new Card(Rank.king, Suit.hearts); assertHashCodeConsistency(card); } private void assertHashCodeConsistency(Card card) { assertEquals(card.hashCode(), card.hashCode());´ }
Okay, that passes. In fact, it’s going to be pretty hard to get it to fail unless we start doing some interesting things with the state of a Card object.