没有 ClassCastException 被抛入 Java 泛型中

2022-09-04 00:54:54

以下是我写过的第一个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()");
        }
    }

}

结果是“CastToOtherType()之外的异常”。为什么泛型方法中没有发生异常?


答案 1

T在编译过程中被有效地擦除。请参阅此处

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

  • 如果类型参数未绑定,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码仅包含普通类、接口和方法。
  • 如有必要,插入类型转换以保持类型安全。生成桥接方法以保持扩展泛型类型中的多态性。
  • 类型擦除确保不会为参数化类型创建新类;因此,泛型不会产生运行时开销。

因此,您将被删除到以下单元格中:castToAnotherTypeT

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

这显然不会产生任何.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()");
    }
}

这会产生 当尝试强制转换为 .ClassCastExceptionObjectString

请参阅泛型教程的类型擦除部分。


答案 2

好吧,由于编译器擦除了泛型类型参数,因此方法内部的强制转换基本上等效于:

    Object ret = null;
    try {
        ret = (Object) param;
    } 
    ...

这不是问题,无论你传递给你的方法是什么(因为任何对象都可以强制转换为对象)。

但是,当您尝试将该对象分配给字符串时,在 main 方法中,会发生 ,因为不能强制转换为 .ClassCastExceptionObjectString


推荐