2

问题_1

class A {}
class B extends A {}

A aObj = new A();
B bObj = new B();

我们知道下面会在运行时导致类转换异常。

List<B> list_B = new ArrayList<B>();
list_B.add((B)aObj); //ClassCast exception

List<? extends A> list_4__A_AND_SubClass_A = new ArrayList<B>();
List<A> list_A = (ArrayList<A>)list_4__A_AND_SubClass_A;
list_A.add(aObj); // No exception here, Why?

问题2

在下面的方法中

void method(List<? extends A> list_4__A_AND_SubClass_A){
   //How do i find the passed list is of Type A or B ??
   // To decide List<A> list_A = (ArrayList<A>)list_4__A_AND_SubClass_A;
   //        OR List<B> list_B = (ArrayList<B>)list_4__A_AND_SubClass_A;
}

更新

Q_1

更好的是,我应该避免参考下面的集合进行修改;除非我们非常确定通过的列表是 A/B 类型;以保持该列表的完整性。

 List<A> list_A = (ArrayList<A>)list_4__A_AND_SubClass_A; 

Q_2

我认为我们可以从调用方方法向调用方方法再传递一个参数,以在调用方法处进行修改时保持列表的完整性。

void method(List<? extends A> list_4__A_AND_SubClass_A, Class<? extends A> obj){
     if (A.class.isAssignableFrom(obj)) {
         List<A> list_A = (List<A>)list_4__A_AND_SubClass_A;
            list_A.add(new A());
            list_A.add(new B());
     } else if (B.class.isAssignableFrom(obj)){
         List<B> list_B = (List<B>)list_4__A_AND_SubClass_A;
            //list_B.add(new A()); //only we can add B
            list_B.add(new B());
     }
}
4

3 回答 3

2

理想情况下,从List<B>to的转换List<A>应该在运行时抛出异常;不幸的是,Java 无法在运行时做出决定。幸运的是,在编译时,您会收到该演员表的警告。

于 2013-03-06T19:14:44.607 回答
1

这一行:

List<A> list_A = (ArrayList<A>)list_4__A_AND_SubClass_A;

产生“未检查”警告,因为您可能(并且确实是)将仅包含Bs的列表转换为可以包含Bs或的列表As(请记住,因为 B 是 A 的子类,它是A),所以下一行

list_A.add(aObj);

完全可以,因为您没有注意警告。

一般来说,对于泛型,List< ? extends A>并不总是与List<A>.

回答问题 2。
不幸的是,所有泛型都是在编译时检查的,并且在运行时可用的信息并不多,因此在运行时,您只有一个对象列表,无法有效地测试这是什么类型的列表。这个“特性”是在 Java 1.5 中引入的向后兼容性和泛型之间的折衷。

于 2013-03-06T19:42:31.410 回答
0
  1. 您在这里List<? extends A>定义通配符类型,这意味着 list 接受任何A来自A. 因此它不会抛出异常

  2. 您无法在这里检测到列表的具体内部类型您必须直接传递它,即您的方法签名必须如下

    无效方法(列表列表)

于 2013-03-06T19:19:02.087 回答