2013-08-07 11 views
26

Wreszcie eksperymentuję trochę z rodzajami. Wpadłem na ten kawałek kodu:Java: Eksperymentowanie z generycznymi

public class Test { 

    static <T> void f(T x) { 
     x = (T) (Integer) 1234; 
     System.out.println(x); 
    } 

    public static void main(String[] args) { 
     f("a"); 
     f(1); 
     f('a'); 
     f(1.5); 
     f(new LinkedList<String>()); 
     f(new HashMap<String, String>()); 
    } 
} 

wpadłem to i dostał ten wynik:

1234 
1234 
1234 
1234 
1234 
1234 

bez wyjątków! Jak to jest możliwe?

+0

Uważaj - niebezpiecznie zbliżasz się do pytania: "Dlaczego generyczne produkty nie działają jak szablony C++?" –

Odpowiedz

36

To z powodu type erasure (dużo napisano o tym, wystarczy google dla tego terminu). Po kompilacji f do kodu bajtowego metoda może wyglądać następująco:

static void f(Object x) { 
    x = (Object) (Integer) 1234; 
    System.out.println(x); 
} 

Więc System.out.println po prostu wywołać metodę toString na obiekcie x - iw Twoim przypadku jest Integer.toString().

+1

To wspaniała odpowiedź :) –

3

Z powodu usunięcia typu. Od Oracle's documentation:

generyczne zostały wprowadzone do języka Java, aby zapewnić mocniej typu kontrole w czasie kompilacji oraz wspieranie programowania generycznego. Aby zaimplementować rodzajowych, kompilator Javy dotyczy typu skasowaniu do:

  • Wymień wszystkie parametry typu w ogólnych typów z ich granicach lub Object jeśli parametry typu są nieograniczone. W związku z tym wygenerowany kod bajtowy, , zawiera tylko zwykłe klasy, interfejsy i metody.

  • Wstawić odlewy w razie potrzeby, aby zachować bezpieczeństwo typu.

  • Generowanie metod mostkowania w celu zachowania polimorfizmu w rozszerzonych rodzajach ogólnych.

Usunięcie typu zapewnia, że ​​nie są tworzone nowe klasy dla sparametryzowanych typów ; w związku z tym, generics nie ponoszą kosztów runtime.

+3

Podczas kopiowania słów z zasobu zewnętrznego zawsze upewnij się, że prawidłowo cytujesz i łączysz oryginalne sformułowanie. –