给出以下代码:
public class ClassCastTest {
private static class GenericHolder<T> {
private T object;
public GenericHolder(Object object) {
this.object = (T) object;
System.out.println(getObject());
}
public T getObject() {
return object;
}
}
public static void main(String[] args) {
GenericHolder<String> foo = new GenericHolder<>(3l);
System.out.println(foo.getObject());
}
}
为什么Java在main方法的第二行而不是GenericHolder的第二行抛出ClassCastException?
答案 0 :(得分:6)
由于在该语言中实现了泛型的方式,您对(T)
的强制转换实际上并没有做任何事情。只有当你以一种实际输出具体类型的方式使用泛型类型时才会这样 - 这里,System.out.println
期望String
并且它会使用强制转换来获取它 - 运行时实际上可以进行任何转换。
就Java运行时而言,GenericHolder<String>
和GenericHolder<Integer>
之间没有区别;他们都持有Object
。 Java只是在从泛型类型中获取具体类型的任何地方插入强制转换。
研究 type erasure 了解更多详情。
答案 1 :(得分:2)
除了路易斯的答案之外,有必要指出,在T
有限的情况下,通过写(T)
来投射到T
会做“做某事”。例如,如果你写
private static class GenericHolder<T extends CharSequence>
而不是行
this.object = (T) object;
投出ClassCastException
,因为您无法将Long
投放到CharSequence
(请注意问题3l
而不是31
{1}})。但是,它不会尝试转换为String
,因为在运行时不知道类型T
。