2012-12-10 19 views
8

Próbuję napisać funkcję, która wymaga pewnych ciągów i robi coś z nimi.Pozwalanie funkcji java akceptować kolekcję lub tablicę

Jedyna rzecz, którą mam zamiar zrobić, to zestaw ciągów jest nad nimi pętlą. Teraz ja skończyć z nietypowej konstrukcji wzdłuż linii

public void foo(String[] myStrings){ 
    foo(java.util.Arrays.asList(myStrings)); 
} 

public void foo(Iterable<String> myStrings){ 
    for(String i : myStrings){ 
     bar(i); 
    } 
} 

który czuje się zbędny ponieważ

for(String i : myStrings){ 
    bar(i); 
} 

byłoby całkowicie poprawny kod myStrings typu String [].

Czy istnieje klasa, którą mogę zaakceptować, co pozwoli zarówno na kolekcje, jak i tablice?

Odpowiedz

8

Zobacz Why is an array not assignable to Iterable?

Krótka odpowiedź: nie. Typy tablicowe są kodami syntetycznymi, tak jak je rozumiem, a zatem nie implementują Iterable ani żadnych innych typów. Musisz podać metodę przeciążenia lub poprosić klientów o zadzwonienie pod numer Arrays.asList w witrynie połączenia.

+1

Dzięki, myślę, że wciąż próbowałem przekonać java, że ​​głęboko w jego sercu był python. – BostonJohn

+1

Haha, nie klikaj tutaj - przepraszam. :) –

+1

Witamy w świecie pełnym pisania. Java jest oparta na zasadzie WET zamiast DRY (jak w Write Everything Twice zamiast Dont Repeat Yourself). – akuhn

3

Niestety, tablica nie implementuje Iterable, mimo że pętla działa na obie.

Można wyłącznie akceptować tylko Iterable, ponieważ przechodzenie wokół tablic jest nieco starą szkołą (zalety wydajności tablic ponad ArrayList są znikome). Istniejąca tablica może być łatwo opakowana i przekształcona na List przy użyciu Arrays.asList(T... a).

+0

To jest dobre połączenie. Używam ArrayLists w każdym nowym kodzie, który piszę, ale jest wiele tablic pływających po tym, co odziedziczyłem. – BostonJohn

1

Mimo że tablice mogą być używane w pętli for-each, nie implementują one Iterable. Są po prostu dwie możliwości, albo przeciąż metodę, jak już wspomniano, albo po prostu podaj tylko wariant iterowalny i zmuś klienta, aby zadzwonił pod numer Arrays.asList().

W przypadku, gdy chcesz również przeciążenie tablicy, można zmienić swój podpis z prostej tablicy do varargs:

public void foo(String... myStrings){ 
    foo(java.util.Arrays.asList(myStrings)); 
} 

W takim przypadku, strzeżcie się niezgodności między prymitywnych tablic i tablic prymitywny-Wrapper:

static void foo(int... ints) {} 
foo(new Integer[] {1, 2}); // compile error 

oraz:

static void foo(Integer... integers) {} 
foo(new int[] { 1, 2 }); // compile error 

A najbardziej niejasny część z varargs Generic:

static <T> T[] foo(T... ts) { 
    return ts; 
} 

Jeśli przekazać tablicę liczb całkowitych:

Integer[] integers = { 1, 2 }; 
System.out.println(Arrays.deepToString(foo(integers))); 
> [1, 2] 

Wartość ts jest tablicą liczb całkowitych z 2 elementów: 1 i 2 .

Jeśli jednak przekazać tablicę prymitywnych wskazówki, zabawna rzecz się dzieje:

int[] ints = { 1, 2 }; 
System.out.println(Arrays.deepToString(foo(ints))); 
> [[1, 2]] 

W tym przypadku, wartość ts jest tablicą int tablic (int[][]) tylko z jednego elementu, który jest pierwotnie przekazaną tablicą. Powodem jest to, że int nie jest Object (autoboxing nie pomaga tutaj), podczas gdy tablica ints jest, więc wartość parametru typu T staje się int[].