Name: joT67522 Date: 08/28/97
The implementation of Hashtable.put() makes creating classes that
extend Hashtable and reimplement put and get very dangerous, in a
subtle and undocumented way.
Consider a class, say OrderedHashtable, that extends Hashtable
and implements its own get and put methods. OrderedHashtable
wants to maintain the insertion order of entries in the table by
keeping a separate linked list of OrderedHashtableEntry objects,
each of which wraps an Object that was passed into its put()
method. The Objects stored in the underlying Hashtable are
instances of OrderedHashtableEntry, not the origial objects that
were passed to OrderedHashtable.put
(One can argue about the merits of this implementation and
suggest that the right relationship is OrderedHashtable HAS-A
Hashtable, rather than IS-A Hashtable, but that's beside the
point for now.)
Given the class described above, you get the following scenario
when the base Hashtable runs out of space:
(1) Client calls OrderedHashtable.put on some object (O) of
type T, with some key (K) of type String.
(2) OrderedHashtable constructs a wrapper (W) of type
OrderedHashtableEntry around O and calls super.put(K, W)
to put it into the base hashtable. This is usually okay
because OrderedHashtable.get will unwrap the value
for you and return O.
(3) If the hashtable is nearly full, Hashtable.put extends
the underlying data structure AND THEN RECURSIVELY CALLS
put() TO PUT THE OBJECT INTO THE NEW TABLE.
(4) The call to put resolves to OrderedHashtable.put instead
of to the normal Hashtable.put (because all non-final
methods in Java are virtual), which means
OrderedHashtable.put is now asked to use key K to store
object W instead of the original object O.
(5) OrderedHashtable dutifully complies with this request,
wrapping the value in yet another instance of
OrderedHashtableEntry (W2) and storing that in
the table under key K.
When you go to retrieve the value for K, OrderedHashtable
retrieves W2 and then unwraps it, handing you back W, which
is what it got from the recursive call to put that was made
by the Hashtable internals in step (3), but which is NOT the
object you originally asked it to store.
Hashtable should not be calling put() recurisively after
extending the table -- it should use a private method to actually
store data in the table so that subclasses can't get into this
broken state, or else it should extend the table and then store
the value inline in Hashtable.put
company - Art Technology Group , email - ###@###.###
======================================================================