The worry about this approach is that, even though it is safe, the safety is provided at runtime.
What was desired was some mechanism that could be used to ensure that the collections were
used safely at compile time. And thus was born Java Generics, or parameterized types.
I'm not going to try to give a full tutorial on the use of generics in Java here. The subject has
been covered elsewhere, and a full exposition would take up more space than warranted in
this topic. What follows is an attempt to give a good working knowledge of the simplest way
of using generics, especially with the collection classes.
The idea behind generics is reasonably simple, although the details seem to get arbitrarily
complex. The simple idea is that we can have variables in some declarations that vary over
types rather than instances of types. We can then instantiate particular versions of these gen-
erically declared items by binding the type variable to some particular value. The value of
having a variable in the declaration is that it allows us to write code that can deal with all of
the particular instantiations of the type variable to real types.
OK, maybe that last paragraph didn't help. Actually, the best way to get a feel for generics is
to look at how the introduction of generics changed the collection classes. Which shouldn't be
a surprise, since the collections were really the reason that generics were introduced into the
language in the first place.
With the introduction of generics, collections such as a Set can now be declared using a type
parameter. Syntactically, such a parameter follows the type name and is enclosed by brackets.
So now, instead of saying that the return value from the getRoster() method of our Team
interface is a Set , we can declare it a Set<Player> , or a set of Player objects.
If we look at the documentation for the Set interface, we can see that what is documented is
Set<E> . E , in this case, is a type parameter that is used throughout the documentation (and
the definition of the interface). Not only does the declaration of something that is a Set use
this parameter, but the parameter is used in the declaration of the methods of the interface. In
particular, the method used to place an object into the collection is now declared as:
boolean add(E e)
and the method that gives us an iterator is now declared as: