For the second assignment, why is hashCode() overridden in Building? Ah, good question. If you look at the javadoc for Object.hashCode(), you'll find the general contract for hashCode(). General contracts are part of the great lie I mentioned in class; they specify, but do not guarantee, expected behavior. The second requirement in the hashCode() contract is 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. That is, there is an expected relation between equals() and hashCode(), and when changing the behavior of either one of those methods - by, for example, overriding it - you have to make sure the relation still holds. There's no good reason to override Object.hashCode() in Building; however, there's an excellent reason for overriding Object.equals(): it's too strict. Without overriding, (new Building(1, 2, 3)).equals(new Building(1, 2, 3)) returns false, which, while it makes sense given the definition of Object.equals(), is counter-intuitive and confusing with respect to Buildings (essentially, Object.equals() implements identity, while Building.equals() should implement similarity). I overrode Building.equals() to make more sensible, which entailed the obligation to override Building.hashCode() to maintain the contract. Forgetting to override hashCode(), which is easy to do, causes things to break in mysterious and subtle ways. Similar to the example above, the following code prints "true" then "null": Hashtable<Building, String> ht = new Hashtable<Building, String>() System.out.println((new Building(1, 2, 3)).equals(new Building(1, 2, 3))) ht.put(new Building(1, 2, 3), "hello") System.out.println(ht.get(new Building(1, 2, 3))) If I had forgotten to override hashCode(), and somebody used hashing in their assignment, which might be a sensible thing to do, they might have been in for some extremely confusing debugging. findbugs warns you when you override equals() but not hashCode(). Make a copy of Building.java, delete hashCode(), compile it, and run the class through findbugs. I once worked for a company on a compiler written in Java. In almost every case, a class that overrode equals() failed to override hashCode(). One of my colleagues spend a couple of intense weeks working on an error, which he eventually tracked down to a misbehaving hash set. The hash set was being used to count the number of unique items in a list. This is a perfectly good use for sets: throw all the list items into a set, let the set semantics remove the duplicates, and then use the set size as the count. You should be able to anticipate what was wrong: the list items were instances of classes in which equals() was overridden but hashCode() was not. As a result, the set size was too high, causing the problem. Even after my colleague traced the problem to the set size, it took him a few days to figure out why the set wasn't working correctly.Received on Thu Nov 18 2010 - 11:25:58 EST
This archive was generated by hypermail 2.2.0 : Sat Nov 27 2010 - 14:09:40 EST