Java Reference
In-Depth Information
Capture conversion is designed to make wildcards more useful. To understand the mo-
tivation, let's begin by looking at the method
java.util.Collections.reverse()
:
public static void reverse(List<?> list);
The method reverses the list provided as a parameter. It works for any type of list, and
so the use of the wildcard type
List<?>
as the type of the formal parameter is entirely
appropriate.
Now consider how one would implement
reverse()
:
public static void reverse(List<?> list) { rev(list); }
private static <T> void rev(List<T> list) {
List<T> tmp = new ArrayList<T>(list);
for (int i = 0; i < list.size(); i++) {
list.set(i, tmp.get(list.size() - i - 1));
}
}
The implementation needs to copy the list, extract elements from the copy, and insert
them into the original. To do this in a type-safe manner, we need to give a name,
T
, to
the element type of the incoming list. We do this in the private service method
rev()
.
This requires us to pass the incoming argument list, of type
List<?>
, as an argument to
rev()
. In general,
List<?>
is a list of unknown type. It is not a subtype of
List<T>
, for any
type
T
. Allowing such a subtype relation would be unsound. Given the method:
public static <T> void fill(List<T> l, T obj)
the following code would undermine the type system:
List<String> ls = new ArrayList<String>();
List<?> l = ls;
Collections.fill(l, new Object()); // not legal - but assume it was!
String s = ls.get(0); // ClassCastException - ls contains
// Objects, not Strings.
So, without some special dispensation, we can see that the call from
reverse()
to
rev()
would be disallowed. If this were the case, the author of
reverse()
would be forced to
write its signature as:
public static <T> void reverse(List<T> list)
This is undesirable, as it exposes implementation information to the caller. Worse, the
designer of an API might reason that the signature using a wildcard is what the callers