2006-07-15
Regaining a name for a wildcard type
When using generics I run into the same problem over and over: a class has a field of a parameterized type but actually doesn't care about the type. A perfect match for using wildcards. However, within a method the using class needs to call methods of the parameterized type that have arguments of the type parameter - of course just derived from that very object. For example: rotate a linked list.
public class RotateList { LinkedList<?> theList; public void rotate() { LinkedList<?> l = theList; theList.addLast(theList.removeFirst()); } }
This does not compile since an important piece of information is lost between calling removeFirst and addLast: not only don't we know the type of the result but we also don't know that it's the very type parameter of the list we're talking about.
At this point I would normally resign and propagate the list's type parameter to the using class. This way, type parameters spread throughout my code. But there is hope! We can pull out the code into a generic method, parameterized by the list's element type. This way we can give a local name to the wildcard that will convince the compiler that we're doing right:
public class RotateList { LinkedList<?> theList; public void rotate() { // what used to be an unknown type // regains a name in the method // and becomes more useful rotate(theList); } private <T> void rotate(LinkedList<T> l) { l.addLast(l.removeFirst()); } }
Probably not a surprise for generics wizards but I had my aha-moment! Now why do we need an extra method? How about a syntax for introducing a type name within a method?
public class RotateList { LinkedList<?> theList; public void rotate() { <T> List<T> l = theList; l.addLast(l.removeFirst()); } }