blue-sky
blue-sky

Reputation: 53806

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 ?

Upvotes: 4

Views: 235

Answers (3)

Pshemo
Pshemo

Reputation: 124215

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()

Upvotes: 1

bdkosher
bdkosher

Reputation: 5883

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

In summary, we use covariance <? extends Object> when we only intend to take generic values out of a structure. We use contravariance <? 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.

Upvotes: 4

mpartel
mpartel

Reputation: 4492

? 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> does NOT mean "anything that extends Object goes". A simple List<Object> means that.

Upvotes: 4

Related Questions