泛型和ClassCastException

时间:2016-03-22 17:20:30

标签: java generics

给出以下代码:

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?

2 个答案:

答案 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