Why use a wild card capture helper method?

In this particular case it's because the List.set(int, E) method requires the type to be the same as the type in the list.

If you don't have the helper method, the compiler doesn't know if ? is the same for List<?> and the return from get(int) so you get a compiler error:

The method set(int, capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (int, capture#2-of ?)

With the helper method, you are telling the compiler, the type is the same, I just don't know what the type is.

So why have the non-helper method?

Generics weren't introduced until Java 5 so there is a lot of code out there that predates generics. A pre-Java 5 List is now a List<?> so if you were trying to compile old code in a generic aware compiler, you would have to add these helper methods if you couldn't change the method signatures.


I agree: Delete the helper method and type the public API. There's no reason not to, and every reason to.

Just to summarise the need for the helper with the wildcard version: Although it's obvious to us as humans, the compiler doesn't know that the unknown type returned from l.get(0) is the same unknown type of the list itself. ie it doesn't factor in that the parameter of the set() call comes from the same list object as the target, so it must be a safe operation. It only notices that the type returned from get() is unknown and the type of the target list is unknown, and two unknowns are not guaranteed to be the same type.


You are correct that we don't have to use the wildcard version.

It comes down to which API looks/feels "better", which is subjective

    void foo(List<?> i) 
<T> void foo(List<T> i)

I'll say the 1st version is better.

If there are bounds

    void foo(List<? extends Number> i) 
<T extends Number> void foo(List<T> i)

The 1st version looks even more compact; the type information are all in one place.

At this point of time, the wildcard version is the idiomatic way, and it's more familiar to programmers.

There are a lot of wildcards in JDK method definitions, particularly after java8's introduction of lambda/Stream. They are very ugly, admittedly, because we don't have variance types. But think how much uglier it'll be if we expand all wildcards to type vars.