Capture Conversion

Capture conversion is a process undergone by the compiler during type checking that effectively gives a unique, temporary name to a wildcard type that is not directly referencable by the developer, but can be used by the compiler to validate typing in certain operations. Capture conversion strengthens the applicability of wildcards.

Extended Description

Motivation

Consistency information regarding wildcard types is not kept between two uses of the same wildcard type. For example, the fourth statement of the following code raises a compilation error:

List<String> strlist = new ArrayList<>();
strlist.add("some value");

List<?> myList = strlist;
myList.set(0, myList.get(0));

Despite it being obvious that execution of this code would never result in type mismatches, (since the element returned by myList.get(0) is of type String, and myList can store strings), this code fails to compile due to type checking: Because myList's parameter type is a wildcard, ?,

Java does not consider these two ? wildcards as equivalent, even though they represent the same type. In particular, a wildcard is not a named type, so two distinct type references referring to the same wildcard are considered unequal by the compiler. (This means that the compiler considers the return type of myList.get and the parameter of myList.set as completely distinct types.)

Capture conversion helps to alleviate this issue.

Capture Conversion

Capture conversion is a process in which the compiler assigns an actual, inferred type to a wildcard, allowing code referencing the wildcard type to be used in certain contexts, like a method call:

<T> void doSomething(List<T> someList) {
	// Works, because someList.get(0) is an expression of NAMED type T, which is equivalent to the type of the second parameter of someList.set(...)
	// Java checks equality of named types.
	someList.set(0, someList.get(0));
}

This method may be called with a List whose type argument is a wildcard:

List<?> myList = new ArrayList<>();
doSomething(myList); // Valid, despite being called with a list whose type is a wildcard.

In such a case as the method invocation doSomething(myList); above, capture conversion is performed, replacing the wildcard type ? in the type of the expression myList with the actual type Object (see below for detail on what the wildcard is replaced with during capture conversion). The doSomething method is then called with the type parameter Object, similar to as if by ContainingType.<Object>doSomething(myList);.

Capture conversion is performed in certain, language-mandated contexts.

Type Replacement Rules

This allows for otherwise impossible casts in various cases. (See Cast Operator - Notes for examples.)

Examples