Page 2 of 5
Java, like many general-purpose languages, provides several tools for creating generic classes. Different requirements will necessitate using
different tools. In this column I will use the development of a container class as an example since it can accommodate nearly all of the tools a user might wish to use.
For those of you who are not yet familiar with things object-oriented, a container is a class that organizes other objects. Common containers are binary trees, queues, lists, and stacks. Java supplies three container classes with the JDK 1.0.2 release: java.util.Hashtable, java.util.Stack, and java.util.Vector.
Containers have both an organizing principle and an interface. Stacks, for example, may be organized as "first in, last out" (FILO), and their interface may be defined to have two methods -- push() and pop(). Simple containers can be thought of as having the standard methods add and remove. Further, they will have a means to enumerate the entire container, to check to see if a candidate object is already in the container and to test the number of elements being held by the container.
The Java container classes demonstrate some of the problems with containers, especially keyed containers (those containers
that use a key to locate an object). The non-keyed containers like Stack and Vector simply stuff objects in and pull objects
out. The keyed container Hashtable uses a key object to locate a data object. For the keying function to work, the key object
must support a method HashCode that returns a unique hash code for every object. This keying ability works because the Object class defines a HashCode method and thus is inherited by all objects, but it isn't always what you want. For example, if
you are putting objects into your hash table container and you are indexing them with String objects, the default HashCode
method simply returns a unique integer based on the object reference value. For strings, you really want the hash code to
be a function of the string value, so String overrides HashCode and supplies its own version. This means that for any object
you develop, and want to store in a hash table using an instance of the object as the key, you must override the HashCode
method. This insures that identically constructed objects hash to the same code.
But what about sorted containers? The only sorting interface provided in the Object class is equals(), and it's constrained to equating two objects as having the same reference, not having the same value. This is why, in Java,
you can't write the following code:
if (someStringObject == "this") then { ... do something ... }
The above code compares the object references, notes that there are two different objects here, and returns false. You have to write the code as follows:
if (someStringObject.compareTo("this") == 0) then { ... do something ...}
This latter test uses knowledge encapsulated in the compareTo method of String to compare two string objects and return an indication of equality.