Java泛型中不会抛出ClassCastException

Liv*_*ivy 14 java generics classcastexception

下面是我写过的第一个Java泛型:

public class MyClass {

    public static <T> T castToAnotherType(Object param) {
        T ret = null;
        try {
            ret = (T) param;
        } catch (ClassCastException e) {
            System.out.print("Exception inside castToAnotherType()");
        }
        return ret;
    }

    public static void main(String[] args) {
        try {
            String obj = MyClass.castToAnotherType(new Object());
        } catch (ClassCastException e) {
            System.out.print("Exception outside castToAnotherType()");
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

结果是"castToAnotherType()之外的异常".为什么在泛型方法中不会发生异常?

lex*_*ore 15

T在编译期间被有效擦除.看到这里:

泛型被引入到Java语言中,以便在编译时提供更严格的类型检查并支持泛型编程.为了实现泛型,Java编译器将类型擦除应用于:

  • 如果类型参数是无界的,则用泛型或对象替换泛型类型中的所有类型参数.因此,生成的字节码仅包含普通的类,接口和方法.
  • 如有必要,插入类型铸件以保持类型安全.生成桥接方法以保留扩展泛型类型中的多态性.
  • 类型擦除确保不为参数化类型创建新类; 因此,泛型不会产生运行时开销.

所以你castToAnotherTypeT抹去了ca. 下列:

public static Object castToAnotherType(Object param) {
    Object ret = null;
    try {
        ret = (Object) param;
    } catch (ClassCastException e) {
        System.out.print("Exception inside castToAnotherType()");
    }
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

这显然不会产生任何影响ClassCastException.

main(...) 是一个不同的故事,它产生如下:

public static void main(String[] args) {
    try {
        String obj = (String) MyClass.castToAnotherType(new Object());
    } catch (ClassCastException e) {
        System.out.print("Exception outside castToAnotherType()");
    }
}
Run Code Online (Sandbox Code Playgroud)

其生产的ClassCastException尝试投放时ObjectString.

请参阅Generics教程中Type Erasure部分.