THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

The problem is that the way you specify such a type is not the way we just illustrated because generic types
don't form subtypes in the way you might think.


11.2.1. Subtyping and Wildcards


Suppose you want to write a method to sum all of the elements in a Listone of the collection interfaces of
java.util that we describe in Section 21.6 on page 580. Naturally, you can only sum numbers, so you
require that the list that gets passed contains only Number objects. The following code would seem to do the
trick:


static double sum(List list) {
double sum = 0.0;
for (Number n : list)
sum += n.doubleValue();
return sum;
}


The intent is that sum can be passed any List object that has elements that are compatible with Number.
But that is not what the parameterized type List means: It means an object compatible with
List that has elements declared to be Number. If you try to invoke sum with a List, for
example, your code will not compile.


List l = new ArrayList();
l.add(1);
l.add(4);
l.add(9);
double sum = sum(l); // INVALID: won't compile


The problem is that even though Integer is a subtype of Number, List is not a subtype of
List. Contrast this with arrays, where Integer[] is a subtype of Number[].


We need a way to declare a List of an arbitrary element type that is compatible with Number, and the way
to do that is to use the type argument wildcard '?':


static double sum(List<? extends Number> list) {
double sum = 0.0;
for (Number n : list)
sum += n.doubleValue();
return sum;
}


In this example, the wildcard indicates that we require a List of any type, as long as that type is Number or
a subclass of Number. More formally, we've used a bounded wildcard, where Number forms the upper
bound on the type that is expected: Whatever type we get, it must be at least a Number.


You can also specify that a wildcard type must be the same as, or a supertype of, another. You do this by
using the keyword super rather than extends. For example, you could use List<?superInteger> to
match a List of Integer or any of its supertypes: List, List,
List, List<Comparable>, or List. In this case the type
represents the lower bound on the wildcard's type.