2012-12-20 14 views
9

Dostałem ten jeden z pogawędki układanki we/wy Google podanej przez Joshua Blocha. Oto kodUsuwanie typów generycznych Java z parametrów metody

public class Glommer<T> { 
     String glom(Collection<?> obj){ 
     String result = ""; 
     for(Object o : obj){ 
       result += o; 
     } 
     return result; 
     } 

     int glom(List<Integer> ints){ 
      int result = 0; 
      for(int i : ints){ 
       result += i; 
      } 
      return result; 
     } 

     public static void main(String args[]){ 
      List<String> strings = Arrays.asList("1", "2", "3"); 
      System.out.println(new Glommer().glom(strings)); 
     } 

to główna metoda zgłasza wyjątek, ponieważ new Glommer to rodzaj surowego i stąd wszystkie leki generyczne w Glommer zostanie skasowany, więc kończy się wywołaniem int glom(List<Integer> ints) zamiast String glom(Collection<?> obj).

Moje pytanie brzmi, nawet jeśli zadzwoniłem glom() jak new Glommer<Integer>().glom(strings) nie powinno wywołać metodę int glom(List<Integer> ints) ponieważ ze względu na typ skasowaniu, metoda ta jest skutecznie int glom(List ints) i strings jest typu List nie Collection?

Odpowiedz

7

Wywoływana metoda jest określana w czasie kompilacji, a nie w czasie wykonywania.

Po dodaniu parametru do wywołania konstruktora kompilator będzie miał wystarczającą ilość informacji, aby wiedzieć, że musi wywołać pierwszą metodę. W przeciwnym razie jest tak, jakby generics nie istniało. W obu przypadkach wywoływana metoda zawsze pozostanie taka sama w czasie wykonywania.

EDIT Niektórzy ludzie wydają się wątpić, tak oto kolejny przykład:

public class Test { 

    private static void test(Object object) { 
     System.out.println("Object method"); 
    } 

    private static void test(Integer integer) { 
     System.out.println("Integer method"); 
    } 

    public static void main(String[] args) { 
     Object object = Integer.valueOf(0); 
     test(object); 
    } 

} 

Wynikiem jest:

Object method 

można przekazać Integer metodę, ale wszystko, co kompilator wie na kompilacji czas jest taki, że jest to przedmiot. Jvm nie zmienia automagicznie wywołania metody, mimo że Obiekt jest faktycznie liczbą całkowitą.

+0

Powiedziałbym, że kompilator określa podpis metody do wykonania, ale metoda do wykonania jest wybierana w środowisku wykonawczym przy użyciu rzeczywistego typu obiektu. – tcb

+0

@ tcb Dodałem przykład, spróbuj. – WilQu

+0

Rozumiem, co chcesz powiedzieć iw tym przykładzie masz rację, ale moje słowa dotyczyły ogólnego przypadku, w którym możesz mieć klasę pochodną z nadpisanymi metodami. – tcb

0

Dzieje się tak, ponieważ po wywołaniu new Glommer() bez generycznych numerów Generic<Type>() wszystkie dopasowania typu są usuwane z klasy.

Jako zmienną łańcuchową jest List, jeśli nie ma żadnego generycznego <Type>, wówczas będzie pasować do glom(List ints). Sprawdzanie typu nie jest wykonywane do później.

Kiedy tworzymy new Glommer<AnyType> wszystkie typy są pozostawione na miejscu, więc kiedy przechodzimy naszą zmienną strings, to sprawdza się typ. Kompilator może teraz sprawdzić, czy jest to List<Integer>, który nie jest przekazywany do metody glom(Collection<?> obj).

Mam nadzieję, że to pomoże, poproś o wyjaśnienia, jeśli potrzebujesz!

+0

Zmieniono na kompilator. –

1

Możesz przeczytać więcej o Raw Types zrozumieć go całkowicie

Zasadniczo, surowe typy są za pomocą kodu starszych, prawie wszystko w surowym stanie się klasą sam surowy, w tym przypadku tych 2 metod.

Więc kiedy jest surowa nie jest to metoda, która dostaje List i jeden dla Collection więc jej nazwie List jeden, jeśli nie jest surowy, metody nie są surowe również i to wywołać jedną Collection ponieważ ma dodatkowe informacje

Powiązane problemy