Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java wildcards confusing example

I read the following two links for java generics wildcards

Difference between generic type and wildcard type

and

Are wildcard generics really needed?

I still don't understand wildcards as to how this compiles,

public void foo(List<List<?>> t) {
    t.add(new ArrayList<String>());
    t.add(new ArrayList<Integer>());
}

but this does not,

public static void funct2(final List<?> list, final Object something) {
        list.add(something); // does not compile
    }

Aren't we doing the same thing in the second code block as the first?

like image 325
Ashay Batwal Avatar asked Feb 06 '26 16:02

Ashay Batwal


1 Answers

The first example method has a List<List<?>> parameter. The generic type parameter is List<?> and that means "any List of any type", so it accepts an ArrayList<String> and an ArrayList<Integer>. After type erasure, the JVM sees List and ArrayList here anyway. Note that only a List<?> can come out of t now, no matter what went in. But an ArrayList<String> is a List<?> and an ArrayList<Integer> is a List<?> also.

The second example method has a List<?> parameter. The generic type parameter is a simple wildcard -- a specific yet unknown type. It could be a List<String>, a List<Object>, or a List<Foo>; the compiler doesn't know. The compiler must disallow calling the add method with anything but null, because it can't guarantee type safety. The something object being added to the list could be an Integer, and list could be a List<Foo> for all it knows.

The difference is that in the first example, both objects being added are Lists, yet in the second example, a simple Object is being passed to a List that contains an unknown type. The first is allowed and the second is not allowed, as I have explained above.

The semantics of List<List<?>> is "list of lists of any type", but the semantics of List<?> is "list of a specific yet unknown type".

like image 149
rgettman Avatar answered Feb 09 '26 06:02

rgettman