有人可以向我解释为什么以下代码示例中标记为//this line gives a compile error (why?)
的行不起作用吗?
import java.util.ArrayList;
public class GenericCastCheck {
class A{
}
class B extends A{
}
public static void main(String[] args) {
A aObject = new A();
B bObject = new B();
//this line works fine
aObject = bObject;
//this line gives a compile (expected)
bObject = aObject;
ArrayList<A> aList = new ArrayList<A>();
ArrayList<B> bList = new ArrayList<B>();
//this line gives a compile error (why?)
aList = bList;
//this line gives a compile error (expected)
bList = aList;
}
}
具体来说,当我们说bList
属于ArrayList<B>
类型时,是否并不意味着它的每个元素都是B
的实例?如果是,那么如果我们可以将ArrayList<A>
的单个实例转换为B
,那么将其转换为A
会出现什么问题?
感谢。
答案 0 :(得分:10)
问题在于:
ArrayList<A> aList = new ArrayList<A>();
ArrayList<B> bList = new ArrayList<B>();
aList = bList; // if this were valid...
aList.add(new A()); // ...what should happen here?
B b = bList.get(0); // ...and here?
如果对数组执行相同操作,则会在运行时在第4行中获得ArrayStoreException。对于泛型集合,决定在编译时阻止这种事情。
答案 1 :(得分:5)
因为通用是严格的。他们不是协变的
ArrayList<A>
aList只能引用ArrayList
类型的A
来自wiki
与数组不同,泛型类是 既不协变也不逆变。 例如,既不
List<String>
也不List<Object>
是该类型的子类型 其他:// a is a single-element List of String List<String> a = new ArrayList<String>(); a.add("foo"); // b is a List of Object List<Object> b = a; // This is a compile-time error
但是,泛型类型参数可以 包含通配符(一个快捷方式) 仅使用的额外类型参数 一旦)。示例:给出要求 对于对列表进行操作的方法, 任何对象,然后唯一的 可以执行的操作 对象是那些对象 类型关系可以得到保证 为了安全起见。
// a is a single-element List of String List<String> a = new ArrayList<String>(); a.add("foo"); // b is a List of anything List<?> b = a; // retrieve the first element Object c = b.get(0); // This is legal, because we can guarantee // that the return type "?" is a subtype of Object // Add an Integer to b. b.add(new Integer (1)); // This is a compile-time error; // we cannot guarantee that Integer is // a subtype of the parameter type "?"
通配符也可以绑定,例如“
? extends Foo
”或“? super Foo
”表示 上限和下限。 这允许细化允许 性能。示例:给定List<? extends Foo>
,然后元素可以 检索并安全分配到Foo
类型(协方差)。给定List<? super Foo>
,那么Foo
对象就可以 安全地添加为元素 (逆变)。
答案 2 :(得分:0)
的Animesh,
即使B类是A的子类型,ArrayList&lt; B>不是ArrayList的子类型&lt; A&gt;。它与B []在同一行上不是A []的子类型。这是两种独立的无关类型。
答案 3 :(得分:0)
因为C<A>
和C<B>
之间的Java中存在 no 子类型关系,即使A
是B
的超类型,反之亦然。
如果您对维基百科中的详细信息查找共同/反向差异感兴趣。
请注意,在Java数组中是共变的,这意味着A[]
是B[]
的超类型,如果A
是B
的超类型。这就是为什么你有时会得到奇怪的数组转换异常的原因。