5
List<? extends String> list = new Arraylist<String>();
list.add("foo");

Given piece of code gives me compile time error.i don't get it why i can't add string in list. but the code means that we can add the String class object and it's derived class object in the list still i am getting the error why

Aman Gupta
  • 73
  • 3
  • 1
    It doesn't really make sense, since `String` is a **final** class! There is no class which can extend `String`. So, the only thing you should do is define it as `List`. – bobbel Jan 30 '16 at 08:13
  • but how it's taking the reference of the ArrayList which has String as it's object? – Aman Gupta Jan 30 '16 at 08:23
  • Because `List` satisfies `List extends String>`. The difference is *String is a String* but *String may not be a ? that is a String*. – Linus Jan 30 '16 at 08:27
  • http://bayou.io/draft/Wildcard_Case_Studies.html#Tight_Bound – ZhongYu Jan 30 '16 at 09:37

3 Answers3

2

List<?> should only be used when you are not concerned with the data type of the items and interested in operations such as getting size of list etc.

For Example,

public int getSize(List<?> itemList) {
     return itemList.size();
}

It is more of a Read Only list.

You should be using the following if you intend to make a new list of String items.

List<String> list = new Arraylist<>();
list.add("foo");

Alternatively, you can use this:

List<Object> list = new Arraylist<>();
list.add("foo");
user2004685
  • 9,548
  • 5
  • 37
  • 54
1

This will work:

List<? super String> list = new ArrayList<String>();
list.add("foo");

Then your compiler will now, that the caller is to pass a list of objects that are String or a super type.

When you say <? extends String> it means it can be of any type which extends String. That means somebody can pass List and it will accept it.

Look also here: Difference for <? super/extends String> in method and variable declaration

Community
  • 1
  • 1
m.aibin
  • 3,528
  • 4
  • 28
  • 47
1

Essentially List<? extends String> is a List of an unknown type, all that is known is that this type extends String. It does not matter that the variable contains an instance of List<String>.

Now String is final, so there is no subclass... so let's consider:

List<? extends A> list = new ArrayList<A>();

where A is some class with a subclass B. When used, a variable of type List<? extends A> might be an instance of List<B>. We can not add A to it because there is the possibility that an A is not a B.

But you know it will be right? Well, the compiler doesn't, nor does it anticipate the logical connections between the unknown type and what you've instantiated, because in general you may change that variable at runtime.

A similar example exist in the tutorial optimistically named More Fun with Wildcards, where a method accepts (Set<T>, T) and an illegal call is preposed using (Set<?>, String) though the Set<?> variable contains an instance of Set<String>. The issue is the same here, despite the addition of extends.

Linus
  • 894
  • 7
  • 13