Javagenerics中不会抛出ClassCastException

下面是我写过的第一个Javagenerics:

public class MyClass { public static  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()"); } } } 

结果是“castToAnotherType()之外的exception” 。 为什么在generics方法中不会发生exception?

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

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

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

所以你的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; } 

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

在尝试将ObjectString时会产生ClassCastException

请参阅generics教程中的Type Erasure部分。

好吧,既然编译器擦除了generics类型参数,那么方法内部的转换基本上等同于:

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

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

但是,当您尝试将该Object分配给String时,在main方法中,会发生ClassCastException ,因为Object无法强制转换为String

所有generics类型都在已编译的代码中被擦除。 就编译代码而言, castToAnotherType只返回一个Object 。 但是,您的main方法尝试将其分配给String ,并且它不是String ,因此会产生ClassCastException

http://en.wikipedia.org/wiki/Type_erasure

这是因为通用类型擦除,

  T ret = null; try { ret = (T) param; ... 

由编译器翻译成

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