通配符
在泛型中,我们可以用一个通配符”?”来代替一个未知的类型。例如,使用下面的代码为某种animal指定一个cage:
Cage<? extends Animal> someCage = ...;
"? extends Animal"表示一种未知的类型,它可能是animal的一种子类型,也可能是animal自己本身,总的来讲就是某种animal。上面的例子是一种受限通配符,它的上限就是Animal。如果需要装下某种animal的cage,那么就可以被用作是lion cage或者butterfly cage。
如果使用super而不是extends则就可以为未知类型指定一个下限(lower bound)。例如,Cage<? super Animal>表示的也是一种未知类型,其可能是animal的一种超类型(supertype),也可能是animal自己本身。当然,如果我们用<?>来定义一个未知类型,那么这样的未知类型是不受限的。一个不受限的未知类型实质上就是<? extends Object>。
虽然Cage<Lion>和Cage<Butterfly>不是Cage<Animal>的子类型,但是却是Cage<? extends Animal>的子类型。上面已经定义了someCage,那么就可以进行如下赋值:
Cage<Lion> lionCage = ...;
Cage<Butterfly> butterflyCage = ...;
someCage = lionCage; // OK
someCage = butterflyCage; // OK
但是我们还是不能把butterflies和lions直接add到someCage:
interface Lion extends Animal {}
Lion king = ...;
interface Butterfly extends Animal {}
Butterfly monarch = ...;
someCage.add(king); // compiler-time error
someCage.add(monarch); // compiler-time error
如果someCage是一个butterfly cage,那么它装入butterfly是没有问题的,但是却装不了lion。当然,如果someCage是一个lion cage,那么它装入lion是没有问题的,却装不了butterfly。也就是我们不能向someCage种装入任何anmial,那么是不是someCage就没有任何用了呢?其实不然,例如下面的代码就用到了someCage:
void feedAnimals(Cage<? extends Animal> someCage) {
for (Animal a : someCage)
a.feedMe();
}
这样一来,我们就可以把每种animal装入到对应独立的cage中,然后依次调用这个方法,如下:
feedAnimals(lionCage);
feedAnimals(butterflyCage);
或者把所有的animal cage组合起来,然后可以用下面的代码进行代替:
feedAnimals(animalCage);
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
文章评论(0条评论)
登录后参与讨论