是否有可能超级列出一个列表?

时间:2015-07-12 09:37:28

标签: java list casting

这可能听起来有点微不足道,但我真的无法找到问题的症结所在。

List<Dog> dogs = getListOfDogs();
List<Cat> cats = getListOfCats();

feed(dogs);
feed(cats);

public void feed(List<Animal> animals) {
    // feed the animal:
    // depending on the type of animal, I might want to give it
    // different kind of food.
}

class Dog implements Animal { /**/ }
class Cat implements Animal { /**/ }
interface Animal { /**/ }

我的上下文非常类似于上面描述的上下文。 我们还假设getListOfDogsgetListOfCats是固定的,并且没有办法在那一方采取行动。

当然,正如这样,这是一个非法的代码:feed只接受List<Animal>类型,而我只能List<Cat>List<Dog>

由于feed是两种动物几乎完全相同的功能,除了食物种类(我可以通过instanceof进行管理),我想避免复制它,只是改变签名。

有没有办法超级投射两个名单?这样的事情(显然是不正确的):feed((List<Animal>) getListOfDogs());

3 个答案:

答案 0 :(得分:6)

您正在寻找的是:

public void feed(List<? extends Animal> animals) {

这将接受List<Animal>List<Dog>List<Cat>等。您无法向animals添加任何内容,因为它可以是任何类型的列表。如果您访问animals中的项目,则会返回Animal类型的引用。

答案 1 :(得分:4)

feed

然而,您可能不希望这样做,因为您的后续声明:

  

由于public void feed(List<? extends Animal> animals) 是两种动物几乎完全相同的功能,但食物种类除外(我可以通过feed进行管理)...

不要轻易触及instanceof,它通常是错误的工具。相反,参数化instanceof

feed

......然后

private void feed(List<? extends Animal> animals, Food food)

public void feed(List<Dog> animals) {
    this.feed(animals, this.dogFood);
}

......或类似的。

答案 2 :(得分:1)

如果它不允许您直接转换为List<Animal>,那么您可以转换为List而不使用通用参数,然后转换为List<Animal>,但这不是一个好方法

这不是一个好方法,因为一旦你更改了通用参数,你就可以将猫放入你的狗列表中。

相反,Feed函数的参数应该看起来不同

public void feed(List<? extends Animal> animals) {
    // feed the animal:
}

通过这种方式,您可以将动物从列表中取出Animal,但无法将错误类型的动物放入列表中。