开发者

java generic and wild card

开发者 https://www.devze.com 2023-04-03 05:36 出处:网络
In java generic I understood what are the meanign of wild card, super and extends, but didn\'t 开发者_StackOverflow中文版get whydoes not allow me to add anything, and whyallows me to add upto SomeType

In java generic I understood what are the meanign of wild card, super and extends, but didn't 开发者_StackOverflow中文版get why does not allow me to add anything, and why allows me to add upto SomeType in hierarchy, but not above in the hierarchy?

class Animal {}
class Cat extends Animal{}

following method can take list of Animal or sub of Animal i.e Cat, but nothing else and I am not allowed to add anything, if try to add, compiler stops me why ?

void addAminal(List<? extends Aminal> aList){
       aList.add(new Cat()); // compiler error
       aList.add(new Animal()); // compiler error
}

Now following method can take any list of Animal or any super type of Animal, but no sub type of Animal, and I can add objects upto Animal or lower in hierarchy, so when I try to add Object, compiler complains why ?

void addAnimal(List<? super Animal> aList){
     aList.add(new Animal()); // no error
     aList.add(new Cat());     // no error
     aList.add(new Object()); // compiler error why ?
}

Thanks Arya


Suppose you defined a new class:

class Tabby extends Cat {}

And then you did the following:

List<Tabby> aList = new ArrayList<Tabby>();
addAnimal(aList);

There's no surprise that this list should not have an Animal or even a Cat that isn't a Tabby, yet if the compiler didn't flag the error, that's what you would have.

The reason is that hou've specified addAnimal to take a list of something that extends Animal, but that something could be highly restrictive. This, however, would compile:

void addAnimal(List<Animal> aList){
    aList.add(new Cat()); // OK
    aList.add(new Animal()); // OK
}

The use of super also would work, because an instance of either Cat or Animal is an instance of any superclass of Animal.


List<? extends Animal> means List<X> where X is an unknown subtype of Animal.

Therefore it has methods

void add(X item);
X get(int i);

You can't call add(cat), because we don't know if Cat is a subtype of X. Since X is unknown, the only value that we knows is a subtype of X is null, so you can add(null) but nothing else.

We can do Animal a = list.get(i), because the method returns X and X is a subtype of Animal. So we can call get(i) and treat the return value as an Animal.

Conversely, List<? super Animal> means List<Y> where Y is an unknown super type of Animal. Now we can call add(cat), because Cat is a subtype of Animal, Animal is a subtype of Y, therefore Cat is a subtype of Y, and add(Y) accepts a Cat. On the other hand, Animal a = list.get(0) won't work now, because Animal is not a super type of the return type Y; the only known super type of Y is Object, so all we can do is Object o = list.get(0).


The generics only allow you to add an object of the type (or a subtype) of the type given as type parameter. If you put <? extends Animal> it means the list has SOME type that is a subclass of animal. Since you are trying to add a Cat to it, you have to be sure that it is indeed a list of Cats, and not of Dogs.
Basically, when you use a wildcard you will not be able to add new items to such a list (note: I don't have full knowledge and this might not be fully correct, but it seems like this. Forgive me if I'm wrong)

If you want to be able to add any Animal to the list, just use List<Animal>.


Well, When you say ArrayList< ? extends Animal > you are specifying that this list will contain any specific type (as ? refers to a specific/definite type) that is of type Animal or anything inherited from Animal but something definite. So ultimately, as the generics are implemented with Eraser concept (which replaces every generic type in the program by a non-generic upper bound), this list is supposed to contain a specific type but due to ( < ? extends Animal >) you don't know which specific type is that. And hence you are not allowed to add even though types are inherited from Animal.

But when you say ArrayList< ? super Animal >, it means the arraylist contains specific type derived from Animal that is, objects whose base or super type is Animal. Hence it is safe to pass a Animal or anything derived from Animal into this list. The list is treated that way and it is allowed to add objects as mentioned. And hence it works.

Hope it helps!

0

精彩评论

暂无评论...
验证码 换一张
取 消