2010-11-19 4 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(); 
    } 
} 

Но это не так. Кастинг Строка Т не подведет, пока я не использовать возвращаемый объект как-то, как:

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

ответ

4

Вы явно не указали, поэтому T является объектом.

Так смотреть выглядеть следующим образом

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); скомпилирован, работает и не требует кастинга.

Смежные вопросы