Trismegistos
Trismegistos

Reputation: 3882

Add to generic List<?> produce compilation error

Following application produce compilation error in line (*)

ArrayList<?> l = new ArrayList<>();        
l.add(new Integer(1));

compilation error says:

error: no suitable method found for add(C<CAP#1>)
    l.add(o);

Why is that? I thought List should accept anything

Upvotes: 1

Views: 149

Answers (2)

Tamas Rev
Tamas Rev

Reputation: 7166

I generally prefer not to use wildcards. These are the options:

Using a List is for a list with an unknown type:

List<?> list = Arrays.asList(1, 2d, "3"); // can contain any Object
for (Object obj : list) { // you can retrieve them
    System.out.println("--> " + obj);
}
list.add("a"); // compile error

Using <? extends Number> lets you retrieve numbers from a list, but you still can't add anything:

List<? extends Number> list2 = Arrays.asList(1, 2, 3); // can contain any number
for (Number n : list2) {
    System.out.println("--> " + n);
}
list2.add(5); // compile error

List<? extends Number> list3 = Arrays.asList(1, 2d, 3F); // can contain any number
for (Number n : list3) {
    System.out.println("--> " + n);
}
list3.add(5); // compile error

The opposite of <? extends ...> is <? super ...>. This looks weird. The point is that callers of such List<> can add stuff of the appropriate type. Retrieving is a problem though:

List<? super Integer> list4 = new ArrayList<>();
list4.add(1);
for (Integer num : list4) { } // compile error
for (Object num : list4) { }  // this is fine, but not that useful

If you want a flexible data structure, you can use the right supertype. Say for instance, a List<Number> is quite flexible. If you really need to, you can use bound types like List<T extends Number>. You can read more about that at this answer.

Upvotes: 0

Jesper
Jesper

Reputation: 206786

You misunderstood what List<?> means.

It does not mean: a List of any kind of object, so that you should be able to add anything to the List (it is not the same as a raw List or a List<Object>).

It means: a List of a specific, but unknown type. Because the type is unknown, you cannot add anything to the list - the compiler doesn't know what the exact type of the objects in the list should be, so it cannot check if you're not trying to put something into the list that should not be allowed, so it doesn't allow you to add anything to the list.

Upvotes: 5

Related Questions