将List<子类>传递给期望List<超类>的方法

12

我有一个方法需要一个List<SuperClass>作为参数:

public void myMethod(List<SuperClass> list) {}

我想用一个List<Subclass>来调用那个方法,就像这样:

List<SubClass> subList = new ArrayList<>();
// ...
myMethod(subList); // Got an argument mismatch error on this line.

SubClass extends SuperClass时,我不应该能够这样做吗?


1
你没有传递一个子类,而是传递了一个子类的列表。这个列表不是另一个列表的子类。 - Anthony Pegram
2个回答

27
不,泛型不是这样工作的。您可以将您的方法定义为MyMethod(List<? extends SuperClass> list)(按惯例,它应该被命名为myMethod(...))。区别于使用List<SuperClass>List<SubClass>的问题在于,您可以向这些列表中添加新元素,而编译器不会允许您向List<? extends SuperClass>添加任何东西 - 这是有原因的:
考虑以下内容:
class A {}

class B extends A {}

class C extends A {}
如果您现在有一个 List<A>,您可以添加 ABC 的实例。但是,如果将 List<B> 作为 List<? extends A> 参数传递给方法,则编译器不知道是否允许向该列表中添加 AC 的实例(事实上不允许这样做,但如果传递的是 List<A> 则允许)。因此,编译器限制了您不能这样做。
将参数定义为 List<A> 告诉编译器将这三个类的实例放入该列表中是可以的。如果您被允许将 List<B> 作为这样的参数传递,那么您最终可能会得到一个包含 A 和/或 C 实例的 List<B>。这显然不是您想要的,并且可能导致运行时错误,而这些错误应该在编译时通过使用泛型来预防。这就是为什么您的方法行不通的原因。

谢谢 - 我甚至不确定该搜索什么。顺便说一下,它是“extends”。 - Derek
如果可以的话,我会给这个答案超过一个赞。这是一个很好的解释。谢谢。 - Gaʀʀʏ
非常感谢,这是一个非常有用的解释。 - Alice

1
值得一提的是,你也可以从子类列表中创建超类列表,方法如下:
myMethod(new ArrayList<SuperClass>(list));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接