在java中,只要B
扩展A
,就可以将类B
的实例强制转换为类A
的实例。
对于类型参数化类,是否也可以这样做?例如,B
延长A
,我想执行以下操作:
List<A> l = new ArrayList<B>();
我认为这应该是合法的,但编译器在这一点上并不同意我,所以我用下面的黑客欺骗了它:
List<A> l = (List<A>)(List) new ArrayList<B>();
...但我认为我会被velociraptor击中。这样做有一种优雅的方式吗?
答案 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。