THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

Class IntegerLookup is not itself a generic class, rather it implements a generic interface, providing a
concrete typeIntegerin place of the abstract type parameter T. Compared to the SimpleLookup class,
this class can store items in an array of Integer and find returns an Integer.


How would we modify processValues to work with generic implementations of Lookup? Here's one
attempt to do so:


void processValues(String[] names, Lookup table) {
for (int i = 0; i < names.length; i++) {
Object value = table.find(names[i]);
if (value != null)
processValue(names[i], value);
}
}


This compiles okay, and appears reasonabletable is an instance of a class that implements Lookup for any
kind of Object. As Integer instances are Object instances then we should be able to do this:


Lookup l = new IntegerLookup();
// ... add entries to l ...
String[] names = { "One", "two" };
processValues(names, l); // INVALID: won't compile


But we find that this code won't compile. The problem is that, as defined, processValues will only accept
an instance of a class that implements Lookup, and IntegerLookup does not do that. Even
though Integer is a subtype of Object, Lookup is not a subtype of Lookup
and therefore an instance of the former can not be used where an instance of the latter is required. Is there a
way to declare that we want to deal with an instance that implements Lookup of anything? Yeswe use what
is called a wildcard to specify the type parameter:


void processValues(String[] names, Lookup<?> table) {
for (int i = 0; i < names.length; i++) {
Object value = table.find(names[i]);
if (value != null)
processValue(names[i], value);
}
}


The wildcard is written as? and is read as "of unspecified type", or just as "of some type": table is an
instance of a class that implements a lookup of some type. We don't know what type, and in this example we
don't care. The only thing we know about the type we can lookup is that it must at least be an Object, so we
can invoke table.find and store the return value as an Object. Now we can use IntegerLookup
with processValues without a problem.


Suppose in our application we knew that we would always be looking up Integer or Long or Double,
etc.all the subclasses of the Number class. We know, from the previous example, that we can't define
processValues in terms of Lookup, but there is a way to limit the types that the wildcard can
represent:


void processValues(String[] names,
Lookup<? extends Number> table) {
for (int i = 0; i < names.length; i++) {
Number value = table.find(names[i]);