2010-11-19 68 views
5

我期望这个代码抛出ClassCastException:为什么这种通用演员不会失败?

public class Generics { 
    public static void main(String[] args) { 
     method(Integer.class); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

但事实并非如此。铸造字符串T没有失败,直到我用返回的对象以某种方式,如:

public class Generics { 
    public static void main(String[] args) { 
     method(Integer.class).intValue(); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

背景:我创建了使用JAXB解组一个XML文件中的类。它看起来像这样:

public static <T> T unmarshal(File file, Class<? extends T> clazz) 

根据根元素是否是一个匿名类型或不是,正在返回T或JAXBElement的。 JAXBElement当然不能被铸造成T. 在我的单元测试中,我只调用了unmarshal()而没有对结果做任何事情,一切正常。在代码中,它失败了。

为什么它不直接失败?这是一个错误?如果没有,我想明白为什么。

+1

那么,它*会产生警告。 – Jeremy 2010-11-19 12:54:09

回答

4

您没有明确指定,所以T是Object。

所以查找这个样子的

public class Generics { 

    public static void main(String[] args) { 
     Generics.method(Integer.class).intValue(); 
    } 

    public static Object method(Class<Object> t) { 
     return (Object) new String(); 
    } 
} 

如果指定了泛型参数:

public class Generics { 

    public static void main(String[] args) { 
     Generics.<Integer>method(Integer.class).intValue(); 
    } 

    public static <T> T method(Class<T> t) { 
     return (T) new String(); 
    } 
} 

你会得到异常。

4

如果未明确指定T,则类型擦除将其视为Object。因此,您的String对象可以被铸造...

1

我认为你可以做更强大的方法定义是这样的:

public static <T extends Number> T method(Class<T> t) { 
    return //// some code. 
} 

在这种情况下,行返回新的String()就不能进行编译。

但行返回新的整数(123);被编译,工作并不需要投射。