Składnia inicjalizacji tablicy, gdy nie jest w deklaracji

141

Umiem pisać:

AClass[] array = {object1, object2}

Mogę też napisać:

AClass[] array = new AClass[2];
...
array[0] = object1;
array[1] = object2;

ale nie mogę napisać:

AClass[] array;
...
array = {object1, object2};

Dlaczego jest to blokowane przez Javę?

Wiem, jak to obejść, ale od czasu do czasu byłoby to prostsze.

Na przykład:

public void selectedPointsToMove(cpVect coord) {

    if (tab == null) {
        if (arePointsClose(coord, point1, 10)) {
            cpVect[] tempTab = {point1};
            tab = tempTab;
        } else if (arePointsClose(point2, coord, 10)) {
            cpVect[] tempTab = {point2};
            tab = tempTab;
        } else {
            cpVect[] tempTab = {point1,point2};
            tab = tempTab;
        }
    }
}

To proste pytanie, które nurtowało mnie, odkąd nauczyłem się bawić tablicami w Javie.

Jason Rogers
źródło
Przepraszamy za format tekstu, ale z jakiegoś powodu w Chinach przyciski układu tekstu się nie pojawiają: S
Jason Rogers
w przypadku kodu, po prostu upewnij się, że jest wcięty co najmniej 4 spacjami.
Mat
innym problemem jest to, że w wklejonym kodzie były znaki TAB. To psuje formatowanie.
Stephen C
Oki, dzięki, eclipse używa tabulatorów w wcięciach, więc kiedy kopiuję wklej, wszystko psuje. dzięki za edycję
Jason Rogers
Eclipse można i należy zmienić konfigurację, aby nie używać znaków TAB do wcięć. Nie używaj tego jako wymówki.
Stephen C

Odpowiedzi:

137

Dlaczego jest to blokowane przez Javę?

Musiałbyś zapytać projektantów Java. Może istnieć jakiś subtelny gramatyczny powód tego ograniczenia. Zauważ, że niektóre konstrukcje tworzenia / inicjalizacji tablic nie były w Javie 1.0, a (IIRC) zostały dodane w Javie 1.1.

Ale „dlaczego” jest nieistotne… ograniczenie istnieje i trzeba z nim żyć.

Wiem, jak to obejść, ale od czasu do czasu byłoby to prostsze.

Możesz to napisać:

AClass[] array;
...
array = new AClass[]{object1, object2};
Stephen C.
źródło
9
bez nowej deklaracji nie byłoby różnicy między blokiem instrukcji a inicjatorem tablicy (jak w javascript, co może wprowadzać w błąd}
bestsss
10
To byłoby być mylące ... i trudne do analizowania. Zastanów się, czy {o1()}było to prawidłowe wyrażenie i czy {o1();}był prawidłowym blokiem instrukcji. Parser musi dostać się do '}' lub ';' zanim będzie mógł rozróżnić te dwa przypadki. Zagadnienie gramatyczne wcale nie jest subtelne !!
Stephen C,
19

Spróbuję odpowiedzieć na pytanie dlaczego: tablica Javy jest bardzo prosta i elementarna w porównaniu z klasami takimi jak ArrayList, które są bardziej dynamiczne. Java chce wiedzieć w momencie deklaracji, ile pamięci powinno być przydzielone dla tablicy. ArrayList jest znacznie bardziej dynamiczna, a jej rozmiar może się zmieniać w czasie.

Jeśli zainicjujesz swoją tablicę o długości dwóch, a później okaże się, że potrzebujesz długości trzech, musisz wyrzucić to, co masz, i utworzyć zupełnie nową tablicę. Dlatego słowo kluczowe „nowe”.

W pierwszych dwóch przykładach w momencie deklaracji podajesz, ile pamięci należy przydzielić. W trzecim przykładzie nazwa tablicy staje się wskaźnikiem do niczego, a zatem po jej zainicjowaniu musisz jawnie utworzyć nową tablicę, aby przydzielić odpowiednią ilość pamięci.

Powiedziałbym (a jeśli ktoś wie lepiej, proszę mnie poprawić) na pierwszym przykładzie

AClass[] array = {object1, object2}

właściwie znaczy

AClass[] array = new AClass[]{object1, object2};

ale projektanci Javy przyspieszyli zapis, jeśli utworzymy tablicę w czasie deklaracji.

Sugerowane obejścia są dobre. Jeśli czas lub użycie pamięci jest krytyczne w czasie wykonywania, użyj tablic. Jeśli nie jest to krytyczne i chcesz, aby kod był łatwiejszy do zrozumienia i obsługi, użyj ArrayList.

prograde
źródło
2
To jest skrót, jak powiedziałeś, Cytując Oracle: „Alternatywnie możesz użyć składni skrótu, aby utworzyć i zainicjować tablicę” . Powodem może być to, że w pewnym momencie tablica musi otrzymać trochę miejsca w pamięci, używając nowego. Nowy jest niejawny w skrócie, ale skrót jest ważny tylko w deklaracji. Gdzie indziej nie ma dozwolonego skrótu, a nowy jest obowiązkowy.
min
3
Przepraszam, ale twoja próba odpowiedzi na pytanie „dlaczego” nie wytrzymuje. Kompilator byłby w stanie obliczyć, jak duża powinna być tablica, zliczając wyrażenia między a {i }... tak samo jak w przypadku dozwolonych formularzy inicjalizacyjnych.
Stephen C
8

Nie mogę odpowiedzieć na pytanie dlaczego.

Ale jeśli chcesz czegoś dynamicznego, dlaczego nie weźmiesz pod uwagę kolekcji ArrayList.

ArrrayList może być dowolnego typu Object.

A jeśli jako wymuszenie chcesz, aby była to tablica, możesz użyć na niej metody toArray ().

Na przykład:

            ArrayList<String> al = new ArrayList<String>();
            al.add("one");
            al.add("two");
            String[] strArray = (String[]) al.toArray(new String[0]);

Mam nadzieję, że to ci pomoże.

Amanpreet
źródło
2
Nie ma potrzeby rzutowania zwracanego typu Array na String []. Zgodnie z umową zwracana tablica jest tego samego typu, co określona tablica. docs.oracle.com/javase/6/docs/api/java/util/…
Ankur Agarwal,
4

Dla tych z Was, którzy nie lubią tej potwornej new AClass[] { ... }składni, oto trochę cukru:

public AClass[] c(AClass... arr) { return arr; }

Użyj tej małej funkcji, jak chcesz:

AClass[] array;
...
array = c(object1, object2);
user123
źródło