2010-11-19 14 views
5

Spodziewam ten kod, aby rzucić ClassCastException:Dlaczego ta generyczna obsada nie działa?

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

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

Ale tak nie jest. Casting String do T nie uda, dopóki nie używać zwrócony obiekt jakoś tak:

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(); 
    } 
} 

Tło: I utworzeniu klasy, która używa JAXB do unmarshal plik XML. Wygląda to tak:

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

W zależności od tego, czy korzeń-Element jest anonimowy typ, czy nie, jest zwrocone T lub JAXBElement. Oczywiście JAXBElement nie może być rzutowany na T. W moim teście jednostkowym, w którym nazwałem tylko unmarshal() bez robienia czegoś z wynikiem, wszystko działało dobrze. W kodzie nie udało się.

Dlaczego nie zawodzi bezpośrednio? Czy to błąd? Jeśli nie, chciałbym zrozumieć, dlaczego.

+1

Cóż, * powoduje * wygenerowanie ostrzeżenia. – Jeremy

Odpowiedz

4

Nie określono wprost, więc T jest obiektem.

więc patrzeć wyglądać następująco

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(); 
    } 
} 

przypadku określenia parametru rodzajowego:

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(); 
    } 
} 

dostaniesz tego wyjątku.

4

Jeśli T nie jest jednoznacznie określone, usunięcie typu potraktuje je jako Object. Dlatego Twój obiekt String może być rzutowany ...

1

myślę, że można zrobić silniejszy definicja metody tak:

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

W tym przypadku linii powrotu new String() po prostu nie może być skompilowany.

ale linia zwraca liczbę całkowitą (123); jest skompilowany, działa i nie wymaga przesyłania.

Powiązane problemy