JavaWorld has just published my article on object equality, in which I discuss how to implement the equals
and hashCode
methods in Java. I also go at lengths to point out one of Bloch's Blunders; specifically, that instanceof
should never be used to implement an equality method because that it does not preserve transitivity.
Unfortunately, some Java developers are still under the misconception that because Effective Java uses the antiquated instanceof
approach, that this must be superior. However, even when interviewed on artima.com, he couldn't really come up with a good reason why he didn't use the correct approach in the first place. Reading between the lines, it's obvious that he hadn't come across that method and suffered from the 'Not Invented Here' syndrome, and as a result, hasn't updated the Effective Java book to reflect the correct impementation.
It should be noted that Bloch is no stranger to making bad calls; he was one of the foremost designers in the Collections hierarchy, and made a couple of bad calls:
- He decided that the method
getSize()
, although being part of the JavaBeans coding conventions, was too much to type for developers and so they should havesize()
methods instead. This has caused no end of problems in JSP-like languages, to the extent where special workarounds are needed when presenting the size of a collection in dynamic JavaBean aware systems. - He re-created the
Enumeration
interface, and called itIterator
for no (good) reason. It's not even that most people need to useIterator
'sremove()
method, and it was only a marginal optimisation in general. (You could still use the opaque type instead of the iterator to remove the element in-place.) What he should have done would be to create a subtype of theEnumeration
interface, and added the remove method to that if it were required. - He designed the interfaces to be tightly defined in with the data structures. For example, an interface that allowed you to get/set values dymanically would have had major uses in Java; yet the
Map
interface also defines methods to add/remove/get an iterator along with it. It would not have been that difficult to define interfaces (alalDictionary
to provide abstract data access as well as a slightly more concrete data structure. Now, many developers implementMap
just to provideget
andset
methods, either leaving the others unimplemented, or throwing an exception type.
Of course. Bloch can't be held to blame for all the bad design in Java (he didn't play a part in the fiasco known as the Date
class, which indexes months from 0..11 and counts years since 1900 -- and then goes at anal length to discuss the differences in leap seconds between GMT and UTC), but his design errors and NIH syndrome have affected everyone from Java 1.2 onwards.