2012-05-28 9 views
13

W źródle dla JDK1.6 zbiory metoda klasy Swap jest napisane tak:Dlaczego Collections.swap kopiuje listę wejściową?

public static void swap(List<?> list, int i, int j) { 
    final List l = list; 
    l.set(i, l.set(j, l.get(i))); 
} 

Co powodem jest nie do tworzenia ostatecznej kopii przeszedł liście? Dlaczego po prostu nie modyfikują bezpośrednio przekazanej listy? W takim przypadku otrzymasz również ostrzeżenie typu surowego.

+2

Oto odnośne źródło na Grepcode dla wszystkich zainteresowanych: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#Collections.swap%28java.util.List%2Cint%2Cint%29 –

+1

Co to jest ze spadkiem? –

Odpowiedz

18

Nie ma kopii listy, istnieje tylko kopia odwołania do listy. Ostatnie słowo kluczowe nie jest ważne. Jednak ważne jest, aby użyć typu surowego. Jeżeli parametr byłyby wykorzystywane zamiast, kompilator zgłosi błąd:

public static void swap(List<?> list, int i, int j) { 
    // ERROR: The method set(int, capture#3-of ?) in the type List<capture#3-of ?> 
    // is not applicable for the arguments (int, capture#4-of ?) 
    list.set(i, list.set(j, list.get(i))); 
} 

Oznacza to, że są one za pomocą zmiennej pośredniej do obejścia braków leków generycznych, a pozbyć się komunikatu o błędzie.

Interesujące pytanie brzmi: dlaczego nie używają ogólnej metody? Poniższy kod działa:

public static <T> void swap(List<T> list, int i, int j) { 
    list.set(i, list.set(j, list.get(i))); 
} 

Odpowiedź jest, że metoda ta daje ostrzeżenia w starym kodzie wywołanie metody z surowego typów:

List list = ...; 
// WARNING: Type safety: Unchecked invocation swap2(List, int, int) 
// of the generic method swap2(List<T>, int, int) of type Swap 
Collections.swap(list, 0, 1); 
+0

Więc używają ostatecznego odniesienia do listy, aby uniknąć używania leków generycznych? –

+1

Rzeczywiście, używają zmiennej pośredniej, aby ominąć niedociągnięcia generycznych i pozbyć się komunikatu o błędzie. – nosid

+3

Interfejs API nie powinien być zanieczyszczony szczegółami implementacji metody z parametrem generycznym, w którym wystarczy symbol wieloznaczny (i będzie on bardziej przejrzysty i łatwiejszy do zrozumienia, przy założeniu podstawowej znajomości języka Java). Teraz możesz użyć ogólnej metody jako metody implementacji i mieć publiczne wywołanie metody (typowy idiom), jednak podejrzewam, że dodatkowy kod bajtowy może czasami wywoływać inkrementację HotSpot (lub ktoś się tym niepokoił, nawet jeśli nie robi tego ". t). –

Powiązane problemy