Exploring the Wildcard Capture Pattern in Java Generics

While I was reading the Java Specification and Java Tutorials, I stumbled upon the "wildcard capture pattern" and the "Object cannot be converted to CAP#1" error.

The following code triggers this error:

public class TestCapture {
    public static void main(String args[]) {
        foo(Arrays.asList(0, 1, 2, 3));
    }

    // This is a compile error
    //
    // TestCapture.java:20: error: incompatible types: Object cannot be converted to CAP#1
    //         aList.set(0, aList.get(0));
    //                               ^
    //   where CAP#1 is a fresh type-variable:
    //     CAP#1 extends Object from capture of ?
    // Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
    // 1 error
    static void foo(List<?> aList) {
        aList.set(0, aList.get(0));
    }
}

The error says that the compiler is not able to infer properly the type of object being inserted.

The solution proposed is to use a helper function to "capture" the wildcard type into a parameterized type.

public class TestCapture {
    public static void main(String args[]) {
        foo(Arrays.asList(0, 1, 2, 3));
    }

    // This compiles properly
    static void foo(List<?> aList) {
        fooHelper(aList);
    }
    static <T> void fooHelper(List<T> aList) {
        aList.set(0, aList.get(0));
    }
}

It works because now, the type parameter is specified.

In the first example, it raises an error because the code tries to get (create an object) of the wildcard type instead of just manipulating the whole container.

In essence, wildcard types are for when we don't care about the parameterized type. As soon as the type is used (explicitely or implicitely), then the type must be named.

null is a special value which can be stored in wildcard container:

public class TestCapture {
    public static void main(String args[]) {
        bar(Arrays.asList(0, 1, 2, 3));
    }

    static void bar(List<?> aList) {
        aList.set(0, null);
    }
}

I've never encountered such error in my code but I rarely use wildcard, I have always been using parameterized type. I don't know what I am missing by not using wildcard…