为什么这个通用演员不会失败?

时间:2010-11-19 12:41:01

标签: java generics casting

我希望这段代码抛出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();
    }
}

但事实并非如此。将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)

根据root-Element是否为匿名类型,返回T或JAXBElement。 JAXBElement当然不能投入T. 在我的单元测试中,我只调用unmarshal()而没有对结果做任何事情,一切正常。在Code中,它失败了。

为什么不直接失败?这是一个错误吗?如果没有,我想了解原因。

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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();
    }
}

你会得到那个例外。

答案 2 :(得分:1)

我认为您可以像这样制定更强大的方法定义:

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

在这种情况下,行返回new String()只是无法编译。

但行返回new Integer(123);编译,工作,不需要铸造。