这可能听起来有点微不足道,但我真的无法找到问题的症结所在。
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 { /**/ }
我的上下文非常类似于上面描述的上下文。
我们还假设getListOfDogs
和getListOfCats
是固定的,并且没有办法在那一方采取行动。
当然,正如这样,这是一个非法的代码:feed
只接受List<Animal>
类型,而我只能List<Cat>
和List<Dog>
。
由于feed
是两种动物几乎完全相同的功能,除了食物种类(我可以通过instanceof
进行管理),我想避免复制它,只是改变签名。
有没有办法超级投射两个名单?这样的事情(显然是不正确的):feed((List<Animal>) getListOfDogs());
答案 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
,但无法将错误类型的动物放入列表中。