1

在 java 中,可以将类的实例转换为提供的类B的实例extends 。ABA

这也可以用于类型参数化的类吗?例如,对于B扩展A,我想做以下事情:

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

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

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

……但我想我会被迅猛龙击中。有没有一种优雅的方式来做到这一点?

4

4 回答 4

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

于 2012-10-27T12:19:25.823 回答
2
List<? extends A> l = new ArrayList<B>();

您应该在此处阅读有关 java 中的泛型

于 2012-10-27T12:13:14.047 回答
0

有两种方法可以做到......

-这种处理方式Collections已经完成,原因在编译期间和运行时Array检查,但仅在.CollectionsCompile time

-所以不应该将另一种类型的对象意外添加到另一种类型的 Collection 中,即将 Dog 对象添加到 Cat 集合中。

1.

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


}

2.

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


}
于 2012-10-27T12:22:05.283 回答
0

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

对于泛型,List 和 List 都是 "is a" Collection<E>;也就是说,List 不是 List 的子类,因此不能用 List 代替 List。

您正在寻找的有关泛型的具体内容可以在这里找到,为方便起见,复制如下。

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

于 2012-10-27T12:22:12.483 回答