2013-03-12 18 views
19

Mam zajęcia z zaawansowanego programowania na mojej uczelni i mam problem ze zrozumieniem działania tego kodu.Zaawansowany polimorfizm w Javie

public final class GenericClass<T> { 
    private void overloadedMethod(Collection<?> o) { 
     System.out.println("Collection<?>"); 
    } 

    private void overloadedMethod(List<Number> o) { 
     System.out.println("List<Number>"); 
    } 

    private void overloadedMethod(ArrayList<Integer> o) { 
     System.out.println("ArrayList<Integer>"); 
    } 

    public void method(List<T> l) { 
     overloadedMethod(l); 
    } 

    public static void main(String[] args) { 
     GenericClass<Integer> test = new GenericClass<Integer>(); 
     test.method(new ArrayList<Integer>()); 
    } 
} 

Dlaczego ten kod print "Kolekcja <? >"?

Odpowiedz

14

Deklaracja z method(List<T> l) nie określa żadnych granic dla typu T. Nie ma gwarancji, że T jest liczbą lub podklasą liczby. Dlatego kompilator może zdecydować, że ta metoda wywoła overloadedMethod(Collection<?> o).

Pamiętaj: po kompilacji informacje o rodzajach ogólnych nie będą już dostępne w plikach klas.

+0

dzięki, odpowiedź wyjaśnia jeszcze dlaczego po zmianie 'overloadedMethod (List o)' na 'overloadedMethod (Lista o)' wypisuje programu 'Lista ' zamiast 'Collection ' –

+0

z najważniejsze jest twoje ostatnie zdanie. To wyjaśnia wszystko! –

+0

Bardzo dobra odpowiedź, ale -1, aby zwrócić twoją uwagę na fakt, że deklarowanie "GenericClass " zamiast tego powoduje to samo wezwanie do 'overloadedMethod (Collection )'. Coś tu się dzieje. –

-1

Kiedykolwiek zdefiniować typ rodzajowy, odpowiedni typ surowy jest automatycznie dostarczane ten sposób

public void method(List<T> l) { 

} 

jest zastąpienie

public void method(List<Object> l) { 

} 

jeśli czytasz o wieloznacznych typów, Zobaczysz, że List<Number> i List<Object> lub ArrayList<Integer> i List<Object> nie ma żadnego związku typu. List<Object> jest podtypem Collecion<?> dlatego ta metoda jest wywoływana.

+0

Właściwie to rozumowanie nie wystarcza, aby odpowiedzieć na pytanie. Kompilator decyduje, którą metodę należy przeładować, co ma miejsce * przed * usunięciem typu. –

-1

gdy mamy do czynienia z metodą przeciążenia należy umieścić trzy koncepcje w głowie:

  1. poszerzenie
  2. Boks
  3. Var_args

problem leży w pierwszym punkcie, który powiększa się kompilator java nadaje priorytety każdemu z tych pojęć w takiej samej kolejności, w jakiej są one wymienione powyżej, więc woli poszerzanie i gdy wywołujesz metodę jako test.method(new ArrayList<Integer>()); kompilator stwierdzi, że ArrayList<Integer>() może zostać rozszerzony do Collection<?>, a ponieważ ma najwyższy priorytet, wywołuje te wersje i pomija inne. Uwaga: jeśli zmienisz deklarację pozostałych dwóch metod na private void overloadedMethod(ArrayList<?> o) i private void overloadedMethod(List<?> o), kompilator również wywoła Collection<?> wersja bo to preferowana

+0

Nie, jeśli prywatna pustka jest przeciążonaMethod (lista o) {// następnie zostanie wyświetlona lista metoda nad kolekcją . – AmitG

+0

próbowałeś? –

+0

"@Java Player: Wciąż odwiedzam to forum w biurze i aktualizuję się tak szybko, jak to możliwe. BTW próbowałeś tego? Jeśli próbowałeś, proszę tutaj zakończyć ten wniosek – AmitG