集合<sub>被转换为SuperCollection <super> </super> </sub>

时间:2012-10-27 12:07:55

标签: java casting

在java中,只要B扩展A,就可以将类B的实例强制转换为类A的实例。

对于类型参数化类,是否也可以这样做?例如,B延长A,我想执行以下操作:

List<A> l = new ArrayList<B>();

我认为这应该是合法的,但编译器在这一点上并不同意我,所以我用下面的黑客欺骗了它:

List<A> l = (List<A>)(List) new ArrayList<B>();

...但我认为我会被velociraptor击中。这样做有一种优雅的方式吗?

4 个答案:

答案 0 :(得分:3)

  

我认为这应该是合法的,但编译器在这一点上不同意我的意见

通常,当人类和编译器不同意时,采取编译器方面是安全的。不应该欺骗编译器,而应首先理解为什么它不允许转换。

考虑一下:你制作一个List<B>,就像这样:

List<B> listB = new ArrayList<B>();

到目前为止,每个人都很开心。现在让我们做你认为正确的事情:

// This does not compile, but let's pretend that it does
List<A> listA = (List<A>)listB;

此时,我们listA完全是我们的!让我们一起玩吧:假设我们有另一个C课程A。我们可以这样做吗?

listA.add(new C()); // Why not? The compiler should allow it!

但等等,你看到我们做了什么吗?我们的listB现在包含C!这就是编译器不允许转换的原因;这也是您尝试向列表中添加任何内容时代码不安全的原因。

要解决此问题,您可以使用通配符:List<? extends A>。但是,这会将您的列表限制为只读访问权限。如果你必须允许写作(并且你知道你将只设置正确的东西),请使用非通用的List

答案 1 :(得分:2)

List<? extends A> l = new ArrayList<B>();

您应该阅读java here

中的泛型

答案 2 :(得分:0)

两种方法.......

- 这种处理Collections的方法已经完成,原因Array在编译期间检查,以及运行时,但是{{仅在Collections期间检查1}}。

- 因此不应将其他类型的对象意外添加到其他类型的集合中,即将狗对象添加到Cat集合中。

<强> 1

Compile time

<强> 2

public <T extends A> void go(ArrayList<T> aList){


}

答案 3 :(得分:0)

在非通用上下文中,如果B“是”A,那么B可以代替A,但A不能代替B。

使用泛型,List和List都是“是”Collection<E>;也就是说,List不是List的子类,因此,你不能用List替换List。

您正在寻找的仿制药的具体内容可以在here找到,为方便起见,请在下面复制。

  

给定两个具体类型A和B(例如,Number和Integer),MyClass与MyClass没有任何关系,无论A和B是否相关。 MyClass和MyClass的公共父是Object。