Generic and parameterized types in Java

The code below causes a compile-time error:

The add (capture # 1-of? Extends Object) method in the List type is not applicable for Arguments (String)

code:

List<? extends Object> a1 = new ArrayList(); a1.add("string"); 

Error in line:

 a1.add("string"); 

Since the String class extends from Object, why does ref a1 not accept String?

+4
source share
3 answers

I recommend reading this article http://java.dzone.com/articles/covariance-and-contravariance . (Italic additions of mine)

So we use covariance <? extends Object> <? extends Object> when we intend to use only the general values ​​from the structure. We use contravariance <? super Object> <? super Object> when we are only planning to put common values ​​into the structure and use the <Object> invariant when we intend to do both.

You defined your list as having a covariant object type, which means you can write Object o = a1.get(1) , but you cannot write a1.add("foo") . If you want to be able to add objects but not return them, you will need to define your list as follows:

 List<? super Object> a1 = new ArrayList<>(); 

In my opinion, the authors of the language are a bit unsuccessful using the terms extend and super to denote covariance and contravariance, especially in the above example, since there is no super-type Object .

+4
source

? extends Object ? extends Object means "unknown type X that extends Object ." When you try to add a String to the collection, you basically assert X = String , which the compiler cannot verify. As far as the compiler knows, X could also be an Integer or something completely different.

In other words, List<? extends Object> List<? extends Object> DOES NOT mean that "everything that extends Object goes." A simple List<Object> means that.

+4
source

List<? extends Object> List<? extends Object> can be used with each type of list.

Do you think it would be safe to allow it to add any objects if, for example,

 List<? extends Object> a1 = new ArrayList<Integer>(); a1.add("string"); 

Only the safe value to add will be null , since it does not belong to any particular type.

To get rid of this problem, you can use, for example, List<String> a1 = new ArrayList<String>() or List a1 = new ArrayList()

+1
source

All Articles