Tuesday, 19 April 2011

Lower Bounded Wildcards in Generics

Suppose we wish to write a method called copyTo()such that it copies the data the opposite direction, i.e. from the host object to the given object:
public void copyTo(Box<E> b) {
  b.data = this.data(); 
}

The above code works fine so long as you are copying from one Box to another of exactly the same type (invariant type relationship), e.g. both are Box<Integer> or both are Box<String>. 

But operationally, b could be a Box of any type that is a superclass of E and the copying would be type safe.  This is a contravariant type relationship between Box<E> amd the input parameter to the copyTo() method where the type parameter of the object referenced by the variable b  is a superclass of E.
To express this, we write
public void copyTo(Box<? super E> b) {
  b.data = this.data();  // b.data is a superclass of this.data
}

The type parameterization <? super E> is called a "lower bounded wildcard" because it defines a type that could be any type so long as it is bounded by the subclass E.
Once again, we have greatly increased the utility of the copyTo() method because it is now not limited to only inputs of type Box<E> but will now work with any compatible Box object.
Upper and lower bounded wildcards will prove indispensable when implementing the visitor pattern on generic (parameterized) classes.

No comments:

Post a Comment