简体   繁体   English

Java通用和通配符

[英]java generic and wild card

In java generic I understood what are the meanign of wild card, super and extends, but didn't 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? 在Java泛型中,我理解了通配符,超级和扩展的含义,但是却不明白为什么不允许我添加任何内容,为什么不允许我在层次结构中添加至SomeType,但在层次结构中不包含上述内容?

class Animal {}
class Cat extends Animal{}

following method can take list of Animal or sub of Animal ie Cat, but nothing else and I am not allowed to add anything, if try to add, compiler stops me why ? 下面的方法可以获取Animal或Animal的子列表,即Cat,但是除此之外,我不能添加任何东西,如果尝试添加,编译器会阻止我为什么?

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 ? 现在,以下方法可以采用任何Animal列表或Animal的任何超类型,但不能包含Animal的任何子类型,并且我可以将对象添加到Animal或更低的层次结构中,因此当我尝试添加Object时,编译器会抱怨为什么?

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. 原因是您已指定addAnimal接受扩展了Animal的内容的列表,但这些内容可能具有很高的限制性。 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 . 使用super也可以,因为CatAnimal的实例是Animal的任何超类的实例。

List<? extends Animal> List<? extends Animal> means List<X> where X is an unknown subtype of Animal . List<? extends Animal>表示List<X> ,其中XAnimal的未知子类型。

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. 您无法调用add(cat),因为我们不知道Cat是否是X的子类型。由于X是未知的,所以我们知道的唯一值是X的子类型为null ,因此您可以add(null)但没有别的。

We can do Animal a = list.get(i) , because the method returns X and X is a subtype of Animal . 我们可以执行Animal a = list.get(i) ,因为该方法返回X并且XAnimal的子类型。 So we can call get(i) and treat the return value as an Animal. 因此,我们可以调用get(i)并将返回值视为动物。

Conversely, List<? super Animal> 相反, List<? super Animal> List<? super Animal> means List<Y> where Y is an unknown super type of Animal . List<? super Animal>表示List<Y> ,其中YAnimal的未知超类型。 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. 现在我们可以调用add(cat) ,因为Cat是Animal的子类型,Animal是Y的子类型,因此Cat是Y的子类型,并且add(Y)接受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 ; 另一方面, Animal a = list.get(0)现在将无法工作,因为Animal不是返回类型Y的超类型; the only known super type of Y is Object, so all we can do is Object o = list.get(0) . Y唯一已知的超类型是Object,所以我们所能做的就是Object o = list.get(0)

Well, When you say ArrayList< ? 好吧,当您说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 . 扩展Animal>,您要指定此列表包含任何类型的特定类型(因为?表示特定/确定的类型),该类型为Animal或从Animal继承的任何东西,但为确定的 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. 因此,最终,由于使用Eraser概念实现了泛型(以非泛型上限代替了程序中的每个泛型类型),因此该列表应该包含特定类型,但是由于(<?extended Animal>不知道那是哪种具体类型。 And hence you are not allowed to add even though types are inherited from Animal. 因此,即使类型是从Animal继承的,也不允许添加。

But when you say ArrayList< ? 但是当你说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! 希望能帮助到你!

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> 如果把<? extends Animal> <? extends Animal> it means the list has SOME type that is a subclass of animal. <? extends 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> . 如果您希望能够将任何动物添加到列表中,只需使用List<Animal>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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