2016-07-15 16 views
5

1) OKDlaczego lista <Integer[]> listOfArrays = Arrays.asList (nowa liczba całkowita [] {1, 2}) nie kompiluje się?

List<int[]> listOfArrays1 = Arrays.asList(new int[]{1, 2}); 

2) OK

List<int[]> listOfArrays2 = Arrays.asList(new int[]{1, 2}, new int[]{3, 4}); 

3) Błąd kompilacji Type mismatch: cannot convert from List<Integer> to List<Integer[]>

List<Integer[]> listOfArrays3 = Arrays.asList(new Integer[]{1, 2}); 

4) OK

List<Integer[]> listOfArrays4 = Arrays.asList(new Integer[]{1, 2}, new Integer[]{3, 4}); 

To jest podpis dla asList: public static <T> List<T> asList(T... a)

asList oczekuje 0 lub więcej "a" typu T. My "a" jest new Integer[]{1, 2} i to jest typu Integer[]. Dlaczego więc generuje on List<Integer> zamiast List<Integer[]>? wygląd

+0

Proszę wyjaśnić, w jaki sposób 1 i 2 nie wykazały żadnego błędu. 'List' nie działa z pierwotnym' int'. – Sufian

+2

@Sufian 'int []' nie jest prymitywny. To obiekt. – Gendarme

+0

(1) rozwiązuje poprawnie, ponieważ 'T' może być' int [] ', ale nie' int'. Powiązane http://stackoverflow.com/questions/2721546/why-dont-java-generics-support-primitive- typeses – blgt

Odpowiedz

3

Miejmy na przykład problemu (3):

List<Integer[]> listOfArrays3 = Arrays.asList(new Integer[]{1, 2}); 

Jak pokazały, podpis metoda jest:

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

W tym konkretnym przypadku, pojedynczy Integer[] jest rozważane dla T.... Tablicę lub nieokreśloną liczbę tego samego obiektu można dostarczyć do T.... Ponieważ podałeś jedną tablicę, T jest uważany za Integer (i T... staje się Integer[]).

Kiedy dostarczyć int[] jako pojedynczy argument (1), kompilator nie automatycznie owinąć to do Integer[] bo taki obiekt różni się od int[]. Ponieważ int nie jest obiektem, jedynym typem obiektu, który może zmieścić się T jest int[] (który buduje parametr jako int[][]).

dostarcza dwie int[] s (2) jest znacznie bardziej widoczne, co kompilator może dotyczyć tylko dwie tablice dla T... jak int[] s, co T... jest int[][].

Kiedy dostarczamy dwa Integer[] s (4.), to bardziej oczywiste, znowu, że kompilator nie ma wyboru i musi uznać dwa parametry, które tworzą T... jako Integer[] (który staje się jednym tablica: Integer[][]).

Edit: Zaopatrywanie tablicę jako vararg:

Ty może dostarczyć pojedynczą tablicę jako vararg.Weźmy przykład bez ogólna:

public int iLoveMeSomeInts(int...nums) 

doprowadzania int[] do tej metody jako argument działa. Tablica jest traktowana jako vararg z int s dla celów sprawdzania poprawności podpisu, wtedy wararg jest traktowany jako int[] dla wewnętrznej logiki metody.

Różnica w twoim przykładzie jest taka, że ​​argumentem jest T.... Ogólny obiekt musi być obiektem T , więc kompilator nie może w tym przypadku traktować wartości int[] jako wartości zmiennej z zakresu int.... Kompilator nie ma wtedy innego wyboru, jak tylko traktować int[] jako pojedynczy element w wariancie int[]... (ponieważ obiekt jest obiektem int[]). Nie ma w tym dwuznaczności.

Jednak ponieważ Integerjest obiekt, kompilator użyje pojedynczy Integer[] jak Integer....

Co jeszcze chłodniej jest taka: jeśli chcesz Integer[] zwracane przy użyciu metody w pytaniu, a wciąż tylko zasilany pojedynczą Integer[], można nazwać:

Arrays.<Integer[]>asList(new Integer[] {1, 2}); 

Zmusza kompilator traktują swój pojedynczy Integer[] jako Integer[]....

+0

Myślę, że tak naprawdę nie wiedziałem, jak działają varargs. – Gustavo

+0

varvargs są świetne, ponieważ można podać dowolną liczbę tego samego obiektu, a w samej metodzie ten argument jest traktowany jako tablica. Tutaj mamy do czynienia z tym, że ogólny element 'T' musi być obiektem, więc podanie' int [] 'nie będzie traktowane jako zmienna' int'. – Zircon

+0

Innymi słowy (jeśli dobrze to zrozumiałem), sprawa 3 jest niejednoznaczna, ponieważ może być interpretowana jako dwa argumenty '(1, 2)' i jeden argument '(nowa liczba całkowita [] {1,2})'. Zdarza się, że kompilator decyduje się wybrać pierwszy, a jeśli oczekujesz drugiego wyniku, zaskakuje cię. – Gendarme

Powiązane problemy