Generics of Java 1.5 Tiger - Restricting Type Parameters
(Page 10 of 10 )
Suppose that you want a version of Box that only accepts numbers—and further, that based on that, you want to add some functionality that’s specific to numbers. To accomplish this, you need to restrict the types that are allowed.
How do I do that?
This is pretty simple—you can actually insert an extends className onto your type variable, and voila! Check out Example 2-3.
Example 2-3. Restricting the parameterization type
package com.oreilly.tiger.ch02;
import java.util.Iterator;
public class NumberBox<N extends Number> extends Box<N> {
public NumberBox() {
super();
}
// Sum everything in the box
public double sum() {
double total = 0;
for (Iterator<N> i = contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue( );
}
return total;
}
}
The only types allowed here are extensions of the class Number (or Number itself). So the following statement is illegal:
NumberBox<String> illegal = new NumberBox<String>();
The compiler indicates that the bound of this type is not met. The bound, of course, is the restriction put upon typing, and that’s exactly what the error message indicates:
[javac] code\src\com\oreilly\tiger\ch02\GenericsTester.java:118:
type parameter java.lang.String is not within its bound
[javac] NumberBox<String> illegal = new NumberBox<String>();
[javac] ^
[javac] code\src\com\oreilly\tiger\ch02\GenericsTester.java:118:
type parameter java.lang.String is not within its bound
[javac] NumberBox<String> illegal = new NumberBox<String>();
[javac] ^
You can use this same syntax in method definitions:
public static double sum(Box<? extends Number> box1,
Box<? extends Number> box2)
double total = 0;
for (Iterator<? extends Number> i = box1.contents.iterator();
i.hasNext(); ) {
total = total + i.next().doubleValue();
}
for (Iterator<? extends Number> i = box2.contents.iterator();
i.hasNext(); )
total = total + i.next().doubleValue();
}
return total;
}
This starts to get a little weird, I realize, but them’s the breaks. It gets worse because you have to use the wildcard indicator, and then repeat the expression (? extends Number) in the method body. One way to clean this up is to declare your own type variable inline (and make your syntax even odder):
public static <A extends Number> double sum(Box<A> box1,
Box<A> box2) {
double total = 0;
for (Iterator<A> i = box1.contents.iterator(); i.hasNext( ); ) {
total = total + i.next().doubleValue( );
}
for (Iterator<A> i = box2.contents.iterator( ); i.hasNext( ); ) {
total = total + i.next( ).doubleValue( );
}
return total;
}
The portion of the method declaration right before the return value, <A extends Number>, provides a typing variable which is then used throughout the method declaration and body.
What about…
…the other thousand-and-one variations on this theme? I say that only somewhat tongue-in-cheek, to stress that generics are a huge topic unto themselves. In fact, I suspect that there will be at least a few books entirely on generics alone before 2004 has come to a close, and those books will cover far more than this chapter. It’s worth knowing that there are ways to extend classes and implement interfaces in your type variables, there are ways to require the superclass of a particular object, and a whole lot more.
You can also check
out the in-depth
chapter on
generics in Java in a
Nutshell, Fifth
Edition (O’Reilly).
Of course, there are ways to juggle knives also, but some things just don’t fit into a developer’s notebook. You should have more than enough tools to get most of your programming tasks done, and by the time you’ve got all this mastered, those other books will probably be on bookshelves. So enjoy this, take a deep breath, and turn the page for more Tiger antics.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
|
This article was taken from chapter two of Java 1.5 Tiger: A Developer's Notebook, written by Brett McLaughlin and David Flanagan (O'Reilly, 2004; ISBN: 0596007388). Check it out at your favorite bookstore. Buy this book now.
|
|