java通用和通配符

时间:2011-09-08 07:03:51

标签: java generics wildcard

在java泛型中,我理解了外卡,超级和扩展的含义是什么,但是没有得到为什么不允许我添加任何东西,为什么允许我在层次结构中添加SomeType,但不能在层次?

class Animal {}
class Cat extends Animal{}

以下方法可以列出动物或动物的名单,即猫,但没有别的 并且我不允许添加任何内容,如果尝试添加,编译器会阻止我的原因吗?

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

现在下面的方法可以获取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 ?
}

由于 艾莉亚

4 个答案:

答案 0 :(得分:4)

假设您定义了一个新类:

class Tabby extends Cat {}

然后你做了以下事情:

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

毫无疑问,这个列表不应该有一个Animal或者一个不是Tabby的Cat,但是如果编译器没有标记错误,那就是你将拥有的。

原因是,他已经指定addAnimal列出了一些扩展Animal的内容,但这些内容可能具有很高的限制性。但是,这将编译:

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

使用super也可行,因为CatAnimal的实例是Animal的任何超类的实例。

答案 1 :(得分:1)

List<? extends Animal>表示List<X>,其中XAnimal的未知子类型。

因此它有方法

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

你不能调用add(cat),因为我们不知道Cat是否是X的子类型。由于X未知,我们知道的唯一值是{{1}的子类型} X,所以你可以null而不是其他任何东西。

我们可以add(null),因为该方法返回Animal a = list.get(i)XX的子类型。因此,我们可以调用Animal并将返回值视为动物。

相反,get(i)表示List<? super Animal>,其中List<Y>是未知的超级类型Y。现在我们可以调用Animal,因为Cat是Animal的子类型,Animal是add(cat)的子类型,因此Cat是Y的子类型,Y接受Cat 。另一方面,add(Y)现在不起作用,因为Animal不是返回类型Animal a = list.get(0)的超类型;唯一已知的Y超类型是Object,所以我们所能做的就是Y

答案 2 :(得分:0)

泛型只允许您添加作为类型参数给出的类型(或子类型)的对象。如果你放<? extends Animal>就意味着列表中有一些类型是动物的子类。因为你试图添加一只猫,你必须确保它确实是一个猫的列表,而不是狗的列表。
基本上,当你使用通配符时,你将无法将新项目添加到这样的列表中(注意:我没有完全的知识,这可能不完全正确,但它看起来像这样。请原谅我,如果我是错)

如果您希望能够将任何动物添加到列表中,只需使用List<Animal>

答案 3 :(得分:0)

好吧,当你说ArrayList&lt; ?延伸动物&gt;您指定此列表将包含任何特定类型(作为?指特定/确定类型),其类型为Animal或从Animal继承的任何内容,但明确。因此,最终,由于泛型是使用橡皮擦概念(通过非泛型上限替换程序中的每个泛型类型)实现的,因此该列表应该包含特定类型但由于(&lt lt ;?extends Animal&gt;)你不知道哪种特定的类型。因此,即使类型是从Animal继承的,也不允许添加。

但是当你说ArrayList&lt; ? super Animal&gt;,它表示arraylist包含派生自Animal的特定类型,即基础或超类型为Animal的对象。因此,将Animal或从Animal派生的任何内容传递到此列表中是安全的。列表以这种方式处理,并允许添加如上所述的对象。因此它有效。

希望它有所帮助!