2011-01-25 22 views
16

Ludzie mówią, że metoda asList przekształca tablicę na listę i jej nie kopiuje, więc każda zmiana w "aList" odzwierciedli się w "a". Więc dodawanie nowych wartości w "aList" jest nielegalne, ponieważ tablica ma stały rozmiar.Wątpliwości Arrays.asList()?

Ale, asList() metoda zwraca ArrayList<T>. W jaki sposób kompilator rozróżnia linię 3 od 5. Linia 3 daje mi wyjątek (UnsupportedOperationException).

 String[] a = {"a","b","c","d"};//1 
     List<String> aList = Arrays.asList(a);//2 
     aList.add("e");//3 
     List<String> b = new ArrayList<String>();//4 
     b.add("a");//5 
+5

Nie ma znaczenia, co "ludzie mówią". Ważne, co mówi * Javadoc *. – EJP

Odpowiedz

3

Jest to wyjątek, a nie błąd kompilatora. Jest generowany, gdy program jest uruchamiany, a nie w czasie kompilacji. Zasadniczo rzeczywista klasa, którą zwróci Arrays.asList, ma metodę throw UnsupporteOperationException w metodzie add().

Konkretniej Arrays.asList powróci klasy wewnętrzną zdefiniowaną wewnątrz klasy Arrays które pochodzi od AbstractList i nie realizacji sposobu add. Metoda add z AbstractList faktycznie rzuca wyjątek.

33

Ta lista implementacji, którą otrzymałeś od Arrays.asList jest specjalnym widokiem na tablicę - nie możesz zmienić jej rozmiaru.

Typ zwrotu Arrays.asList() to java.util.Arrays.ArrayList, który często jest mylony z java.util.ArrayList. Arrays.ArrayList po prostu pokazuje tablicę jako listę.

+3

+1 Myślę, że jest to sedno problemu. OP widzi, że typem powrotu jest ArrayList i zastanawia się, dlaczego zachowuje się inaczej niż ArrayList. Idealnie poprawne pytanie. –

+0

Andreas_D, typem zwracanym przez 'Arrays.asList (...)' jest 'java.util.List', a nie' java.util.Arrays.ArrayList'. –

3

Zakłada się, że Arrays.asList() zwraca wartość ArrayList, ale tak nie jest. Arrays.asList() zwraca nieokreśloną implementację List. Ta implementacja po prostu rzuca UnsupportedOperationException na każdą nieobsługiwaną metodę.

4

asList() nie zwraca wartości java.util.ArrayList, zwraca wartość java.util.Arrays$ArrayList. Ta klasa nie obejmuje nawet java.util.ArrayList, więc jej zachowanie może być (i jest) zupełnie inne.

Metoda add() jest dziedziczona z java.util.AbstractList, która domyślnie po prostu rzuca UnsupportedOperationException.

+0

Nie, asList zwraca listę. To, co opisujesz, może być prawdziwe w przypadku konkretnej implementacji Java, ale nie jest czymkolwiek, na czym możesz polegać. – jarnbjo

+0

@jarnbjo - Dotyczy to zarówno Sun Java, jak i GNU Classpath i prawdopodobnie innych implementacji, ponieważ jest to najłatwiejszy sposób na zrobienie tego. Ponieważ chodziło o to, jak kompilator może powiedzieć, chociaż konkretny przykład byłby najłatwiejszy do zrozumienia. – OrangeDog

0

asList zwraca listę o ustalonym rozmiarze, dzięki czemu nie można dodawać do niej nowych elementów. Ponieważ lista, którą zwraca, jest rzeczywiście "widokiem" tablicy, z której została utworzona ("a" w twoim przypadku), ma sens, że nie będziesz w stanie dodawać elementów - tak jak nie możesz dodawać elementów do tablica. Zobacz docs dla asList

9

Read again, rodzaj Arrays.asList jest:

public static <T> List<T> asList(T... a) 

który wyraźnie stwierdza, że ​​asList zwraca obiekt, który implementuje interfejsu java.util.List, nigdzie nie mówi zwróci instancję klasy java.util.ArrayList.

Następnie zauważył, że dokumentacja na List.add mówi:

boolean add (E e)

          Dołącza określony element na końcu tej listy (opcja pracy).

Technicznie rzecz biorąc, za każdym razem użyć zmiennej wpisane jako listy (zamiast ArrayList), należy zawsze uważać, aby oczekiwać, że ta metoda może rzucać UnsupportedOperationException. Jeśli masz pewność, że otrzymasz tylko implementację List, która zawsze ma właściwą semantyczną wartość: .add(), możesz pominąć test na ryzyko błędu, gdy twoje założenie zostanie unieważnione.

1

Kluczem do tego jest wdrożenie List zwrócony przez

List<String> aList = Arrays.asList(a); 

Jeśli spojrzeć na kod źródłowy w Arrays widać, że zawiera wewnętrzną prywatną klasę statyczną ArrayList. To nie jest to samo, co java.util.ArrayList.

5

Manoj,

Rodzaj Powrót Arrays.List jest jakiś nieznany wewnętrzna implementacja interfejsu listy i nie java.util.ArrayList, więc można przypisać tylko do typu listy.

Jeśli przypisać go do ArrayList na przykład da kompilacji Błąd „Niezgodność typów: nie można przekonwertować z listy do ArrayList”

ArrayList<String> aList = Arrays.asList(a);// gives Compile time error 

Z Javadoc „Arrays.asList Zwraca stałym lista rozmiarów poparta przez podaną tablicę. (Zmiany na zwróconej liście "przepisz" do tablicy.) "oznacza to, że dostaniesz tylko widok listy tablicy, który jest tworzony w czasie wykonywania IMO i oczywiście nie możesz zmienić rozmiaru tablicy, więc nie można również zmienić rozmiaru "Arrays.asList".

IMO wewnętrzna implementacja Arrays.asList posiada wszystkie zaimplementowane metody, które mogą zmienić rozmiar tablicy jako -

void add(E e) 
{ 
//some unknown code 
throw(java.lang.UnsupportedOperationException); 
} 

więc kiedy tylko próbować zmienić rozmiar tablicy rzuca się UnsupportedOperationException.

Nadal, jeśli chcesz dodać nowe elementy do tablicy ArrayList, używając takiej składni, możesz to zrobić, tworząc podklasę Arraylist (najlepiej przy użyciu anonimowej podklasy ArrayList). można przekazać typ zwracanej Arrays.List do konstruktora ArrayList, coś takiego (tj publicznego ArrayList (Collection c)). -

List<String> girlFriends = new java.util.ArrayList<String>(Arrays.asList("Rose", "Leena", "Kim", "Tina")); 
girlFriends.add("Sarah"); 

Teraz można łatwo dodać do swojej listy Sarah GF przy użyciu tego samego składnia.

PS - Proszę wybrać tę lub inną jako odpowiedź, ponieważ wyjaśniono wszystko. Twoja niska akceptacja jest bardzo zniechęcająca.

Powiązane problemy