通用类型的ArrayList和接口继承问题

时间:2011-12-23 22:37:06

标签: java generics collections types subclass

我无法理解为什么以下内容不起作用,我确信答案与我不理解的基本内容有关,希望有人可以提供帮助。

我理解在ArrayList中使用接口,如果我有:

public interface Weapon { ... }
public class Gun implements Weapon { ...}
public class Knife implements Weapon { ... }

然后你可以将实施武器的任何东西插入武器数组中:

ArrayList<Weapon> weapons = new ArrayList<Weapon>();
weapons.add(new Gun());
weapons.add(new Knife();

我明白了,但令我困惑的是理解为什么ArrayList<Gun>在其他方面与ArrayList<Weapon>不兼容。为了说明,以下是合法的:

public void interfaceIsTheArgument(Weapon w) { ... }
...
interfaceIsTheArgument(new Gun());
interfaceIsTheArgument(new Knife());

但以下不是:

public void interfaceIsTheArgument(ArrayList<Weapon> w) { ... }
...
interfaceIsTheArgument(new ArrayList<Gun>());
interfaceIsTheArgument(new ArrayList<Knife>());

因为最后一个函数调用报告该方法不适用于其参数。

我的问题是,如果方法知道它的任务是ArrayList并将接口作为泛型类型,为什么不能在最后一个语句中传入刀组的数组列表?

2 个答案:

答案 0 :(得分:13)

要“修复”代码,您需要使用通用的绑定

public void interfaceIsTheArgument(List<? extends Weapon> w) { ... }
...
interfaceIsTheArgument(new ArrayList<? extends Weapon> ());
interfaceIsTheArgument(new ArrayList<Knife>());

关键原因是List<Gun> List<Weapon>的子类。这个事实的原因可以通过以下代码来说明:

List<Gun> guns = new ArrayList<Gun>();
// If List<Weapon> was a super type of List<Gun>, this next line would be allowed
List<Weapon> weapons = guns; // Won't compile, but let's assume it did
weapons.add(new Knife());  // Compiles, because Knife is a Weapon
Gun gun = guns.get(0); // Oops! guns.get(0) is a Knife, not a Gun!

通过使用绑定的<? extends Weapon>,我们说我们将接受Weapon子类的任何泛型类型。使用边界可能非常强大。这种绑定是 upper 绑定 - 我们将顶级类指定为Weapon

还有 lower 绑定,它使用以下语法:

List<? super Weapon> // accept any type that is a Weapon or higher in the class hierarchy

那么,何时使用每一个?记住这个词PECS:“制片人延伸,消费者超级”。这意味着在代码的生产者端(对象创建)使用extends,并在代码的使用者端(对象使用)我们super。一旦你尝试了几次,你将通过经验了解为什么它运作良好。

This SO question/answer很好地涵盖了它。

答案 1 :(得分:4)

这是关于泛型的最常见问题之一。 List<Gun>List<Weapon>,你可以做

List<Gun> gunList = new ArrayList<Gun>();
List<Weapon> weaponList = gunList;
weaponList.add(new Knife());
gunList.get(0).fire(); // ClassCastException

这将破坏仿制药所承诺的类型安全性。