简体   繁体   中英

Generics and parameterized types in Java

The below code causes a compile time error :

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

code :

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

Error is at line :

a1.add("string");

Since class String extends from Object why ref a1 not accept a String type ?

? extends Object ? extends Object means "some unknown type X that extends Object ". By trying to add a String to the collection, you're essentially claiming X = String , which the compiler cannot verify. As far as the compiler knows, X could just as well be Integer or something completely different.

In other words List<? extends Object> List<? extends Object> does NOT mean "anything that extends Object goes". A simple List<Object> means that.

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

In summary, we use covariance <? extends Object> <? extends Object> when we only intend to take generic values out of a structure. We use contravariance <? super Object> <? super Object> when we only intend to put generic values into a structure and we use an invariant <Object> when we intend to do both.

You defined your list as holding a covariant Object type, which means you can write Object o = a1.get(1) but you can't write a1.add("foo") . If you want to be able to add Objects but not get them back, then you would need to define your list like this:

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

It's a bit unfortunate, in my opinion, language authors used the terms extend and super to indicate covariance and contravariance, especially in the above example since there is no super type of Object .

List<? extends Object> List<? extends Object> can be used with every type of lists.

How do you think, would it be safe to let it add any objects if for example

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

Only safe value to add would be null since it doesn't belong to any specific type.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM