Java泛型中不会抛出ClassCastException

时间:2014-11-02 13:21:41

标签: 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()");
        }
    }

}

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

4 个答案:

答案 0 :(得分:15)

编译期间

T被有效删除。见here

  

泛型被引入Java语言以提供更紧密的类型   在编译时检查并支持通用编程。至   实现泛型,Java编译器将类型擦除应用于:

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

因此,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()"); } } 是一个不同的故事,它产生于以下内容:

ClassCastException

在尝试将Object投射到String时产生{{1}}。

请参阅Type ErasureGenerics tutorial部分。

答案 1 :(得分:4)

好吧,由于编译器会删除泛型类型参数,因此方法内部的转换基本上等同于:

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

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

但是,当您尝试将该Object分配给字符串时,在main方法中会出现ClassCastException,因为Object无法转换为String

答案 2 :(得分:3)

所有泛型类型都在已编译的代码中被删除。就编译代码而言,castToAnotherType只返回Object。但是,您的main方法尝试将其分配给String,而不是String,因此生成ClassCastException

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

答案 3 :(得分:3)

这是因为通用类型擦除,

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

由编译器翻译成

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