Java The Complete Reference, Seventh Edition

(Greg DeLong) #1

Chapter 14: Generics 327


Here,Tis bounded by a class calledMyClassand an interface calledMyInterface. Thus,
any type argument passed toTmust be a subclass ofMyClassand implementMyInterface.

Using Wildcard Arguments


As useful as type safety is, sometimes it can get in the way of perfectly acceptable constructs.
For example, given theStatsclass shown at the end of the preceding section, assume that
you want to add a method calledsameAvg( )that determines if twoStatsobjects contain
arrays that yield the same average, no matter what type of numeric data each object holds.
For example, if one object contains thedoublevalues 1.0, 2.0, and 3.0, and the other object
contains the integer values 2, 1, and 3, then the averages will be the same. One way to
implementsameAvg( )is to pass it aStatsargument, and then compare the average of that
argument against the invoking object, returning true only if the averages are the same. For
example, you want to be able to callsameAvg( ), as shown here:

Integer inums[] = { 1, 2, 3, 4, 5 };
Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };

Stats<Integer> iob = new Stats<Integer>(inums);
Stats<Double> dob = new Stats<Double>(dnums);

if(iob.sameAvg(dob))
System.out.println("Averages are the same.");
else
System.out.println("Averages differ.");

At first, creatingsameAvg( )seems like an easy problem. BecauseStatsis generic and its
average( )method can work on any type ofStatsobject, it seems that creatingsameAvg( )
would be straightforward. Unfortunately, trouble starts as soon as you try to declare a
parameter of typeStats. BecauseStatsis a parameterized type, what do you specify for
Stats’ type parameter when you declare a parameter of that type?
At first, you might think of a solution like this, in whichTis used as the type parameter:

// This won't work!
// Determine if two averages are the same.
boolean sameAvg(Stats<T> ob) {
if(average() == ob.average())
return true;

return false;
}

The trouble with this attempt is that it will work only with otherStatsobjects whose type is
the same as the invoking object. For example, if the invoking object is of typeStats<Integer>,
then the parameterobmust also be of typeStats<Integer>. It can’t be used to compare the
average of an object of typeStats<Double>with the average of an object of typeStats<Short>,
for example. Therefore, this approach won’t work except in a very narrow context and does
not yield a general (that is, generic) solution.
Free download pdf