2

Below code :

List<? extends String> genericNames = new ArrayList<String>();
genericNames.add("John");

Gives compiler error :

Multiple markers at this line - The method add(capture#1-of ? extends String) in the type List is not applicable for the arguments (String) - The method add(capture#1-of ?) in the type List is not applicable for the arguments (String)

What is causing this error ? Should I not be able to add Strings or its subtype since I am extending String within the type parameter ?

blue-sky
  • 51,962
  • 152
  • 427
  • 752
  • 8
    Why have you used `? extends String` in first place? You can't store anything apart from `String`, as String class is final, and cannot be extended. – Rohit Jain Dec 21 '12 at 16:30
  • A similar question: [Understanding the use of generics in Java](http://stackoverflow.com/a/11174536/697630) – Edwin Dalorzo Dec 21 '12 at 16:33
  • String cannot be extended because it is **final** (I regretted this some times) – MrSmith42 Dec 21 '12 at 16:34
  • @Rohit Jain I thought this rule may be different for type parameters as no compiler error is displayed for line for : List extends String> genericNames = new ArrayList(); – blue-sky Dec 21 '12 at 16:34
  • This is overgeneralizing, but usually you only want bounded wildcards in method declarations. – Powerlord Dec 21 '12 at 16:42
  • @user470184 there will be no compiler error because, its not about final class, even List extends Object> list; list.add(new Object()) is not valid either. its just how generics were implemented, – PermGenError Dec 21 '12 at 16:47

3 Answers3

12

When you use wildcards with extends, you can't add anything in the collection except null. Also, String is a final class; nothing can extend String.

Reason: If it were allowed, you could just be adding the wrong type into the collection.

Example:

class Animal {

}

class Dog extends Animal {

}

class Cat extends Animal {

}

Now you have List<? extends Animal>

public static void someMethod(List<? extends Animal> list){
    list.add(new Dog()); //not valid
}

and you invoke the method like this:

List<Cat> catList = new ArrayList<Cat>(); 
someMethod(catList);

If it were allowed to add in the collection when using wildcards with extends, you just added a Dog into a collection which accepts only Cat or subtype type. Thus you can't add anything into the collection which uses wildcards with upper bounds.

Piyush Mittal
  • 1,860
  • 1
  • 21
  • 39
PermGenError
  • 45,977
  • 8
  • 87
  • 106
1

String is a final class and cannot be extended. Additionally, for the case you seem to be interested in, you do not need the extends keyword. List<String> will do what you seem to want. That will allow Strings and sub-classes of String (if such a thing could exist, which it can't since String is final).

Aurand
  • 5,487
  • 1
  • 25
  • 35
1

Just want to add to the answer of GanGnaMStYleOverFlow that you can add an object of any subtype of Animal to the following list:

List<Animal> animals = new ArrayList<Animal>();

You should use such list whenever you think that it can contain any kind of animals.

On the other hand, you should use List<? extends Animal> when you want to specify that the list contains some kind of animal but you don't know which one. Since you don't know what kind of animals are there, you cannot add any.

tcb
  • 2,745
  • 21
  • 20