2014-04-28 15 views
7

W poniższym przykładzie metoda foo podaje ostrzeżenie, natomiast bar nie?Ostrzeżenie dotyczące dziedziczenia generycznego języka Java

public class X { 

    static class Y {} 
    static class Z extends Y {} 

    Y y = new Y(); 

    <T extends Y> T foo() { 
     return (T) y; // warning - Unchecked cast from X.Y to T 
    } 

    Z bar() { 
     return (Z) y; // compiles fine 
    } 

} 
+5

Ile wiesz o wymazywaniu typu? Zobacz http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Type Erasure –

+1

Myślę, że jest jasne, że 'foo()' powinno dać ostrzeżenie. Rzucasz obiekt 'y' do jakiejś nieznanej nadklasy' T' z 'Y'. Jestem również bardzo zainteresowany tym, dlaczego 'bar()' nie. Domyślam się, że kompilator może zobaczyć, że rzutowanie 'Y' na' Z' nie powoduje problemów, ponieważ dostępna jest definicja 'Z'. – SebastianH

+2

@SebastianH: Nie sądzę, że to problem. – gudge

Odpowiedz

1

Typ T jest usuwany do Y podczas kompilacji, tak jak generics działa w Javie. Tak więc, gdy rzutowanie jest wykonywane w czasie wykonywania, typ T nie jest dostępny, jest to po prostu kodw kodzie bajtowym.

kompiluje dobrze, ponieważ wszystkie informacje o typie są dostępne (nie można obsadzić rzutowania). Jednak foo() brakuje informacji tego typu i nie może zawieść, potencjalnie (lub oczywiście w tym przypadku) renderowania podpisu typu metody niepoprawny i staje się źródłem błędów w programie.

Aby to zrobić bezpiecznie, musisz przekazać samą klasę do metody.

<T extends Y> T foo(Class<T> cls) { 
    return cls.cast(y); //No type warning. Will throw an error when cast fails. 
} 
+0

Ups, zapomniałem o przedłużeniu bit. Edytowane, dzięki. – ggovan

0

Ponieważ T jego tag rodzaj i Z jego nazwy klasy. return (Z) y; jego prawidłowy rzut, ale return (T) y; - rzutowanie na nieznany typ w środowisku wykonawczym. JVM nic nie wiadomo o tagach typów w środowisku wykonawczym (patrz sekcja samouczka this). W absolutnie krótkim, return (T) y;, równoważnie return (Object) y;, odznaczono odlewanie z X.Y na Object. Zobacz także wyjaśnienie na temat downcasting in Java dla return (Z) y;.

+2

"*" return (T) y; "prawie równoważny" return (Object) y; '*" faktycznie od '' jest równoważny w kodzie bajtowym do 'return (Y) y;'. – Pshemo

+2

@Pshemo Oczywiście, dzięki za korektę. – injecto

Powiązane problemy