我只是想知道,为什么错误类型值的赋值不会导致任何运行时异常。我准备了一个小例子,其中类X包含一个实现接口A的通用变量“object”,而类Y声明这个泛型是B类型
public interface A{};
public class B implements A{}
public class C implements A{}
public class X<T extends A>{
T object;
void setObject(T t){
object = t;
}
T getObject(){
return object;
}
}
public class Y extends X<B>{}
如果我有一个X hold和Y-Object类型的变量,编译器允许分配任何值,这在我看来是正确的。但是在运行时,我会期待一个例外。
public static void main(String[] args) throws Exception{
X<A> foo = (X<A>) Class.forName("com.abc.Y").newInstance();
foo.setObject(new B()); //should not fail
foo.setObject(new C()); //should fail
}
在Y类尝试访问该对象之前,我没有任何异常。
如果我将此方法添加到类Y,我在setObject上得到ClassCastException,但实际上我不想用正确的Class覆盖所有方法。
public class Y extends X<B>{
void setObject(B t){
super.setObject(t);
}
}
答案 0 :(得分:2)
原因是因为您在运行时using Reflection生成对象,而泛型只在编译时检查。
这是因为使用type erasure实现了Java Generics。也就是说,它们在编译代码中是not present。
答案 1 :(得分:1)
这种行为的原因是java的类型擦除。 类型擦除通常意味着所有泛型都被java转换所取代(这就是为什么你得到ClassCastException)。 所以这个:
List<String> list = new ArrayList<String>();
list.add("text");
String x = list.get(0);
将转换为:
List list = new ArrayList();
list.add("text");
String x = (String) list.get(0);
您可以在此处详细了解: http://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure