Синтаксис ініціалізації масиву, коли його немає в декларації


141

Я можу написати:

AClass[] array = {object1, object2}

Я також можу написати:

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

але я не можу написати:

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

Чому це заблоковано Java?

Я знаю, як обійти це, але час від часу було б простіше.

Наприклад:

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;
        }
    }
}

Це просте запитання, яке мене клопоче, коли я навчився грати з масивами на Java.


Вибачте за текстовий формат, але чомусь у Китаї кнопки розміщення тексту не з’являються: S
Джейсон Роджерс

Щодо коду, просто переконайтеся, що він з відступом 4 пробілів або більше.
Мат

інша проблема полягає в тому, що у коді, який ви вставили код, у вас були символи TAB. Це зіпсує форматування.
Стівен C

Окі, спасибі, eclipse використовує вкладки в відступі, тому коли я копіюю вставку, це переплутує речі. дякую за редагування
Джейсон Роджерс

Eclipse можна і потрібно налаштувати так, щоб не використовувати символи TAB для відступу. Будь ласка, не використовуйте це як виправдання.
Stephen C

Відповіді:


137

Чому це заблоковано Java?

Вам доведеться запитати дизайнерів Java. Можливо, є якась тонка граматична причина обмеження. Зауважте, що деякі конструкції створення / ініціалізації масиву не були в Java 1.0, а (IIRC) були додані в Java 1.1.

Але "чому" несуттєво ... обмеження існує, і вам доведеться з цим жити.

Я знаю, як обійти це, але час від часу було б простіше.

Ви можете написати це:

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

9
без нової декларації не було б різниці між блоком операторів і ініціалізатором масиву (як у JavaScript, який може вводити в оману}
bestsss

10
Це було б заплутано ... і важко розібратися. Поміркуйте, чи {o1()}було виразним виразом і чи {o1();}був допустимим блоком операторів. Аналізатор повинен дістатися до '}' або ';' перш ніж він зможе розрізнити два випадки. Граматичне питання зовсім не тонке !!
Стівен С

19

Я спробую відповісти на питання, чому: Масив Java дуже простий і рудиментарний порівняно з такими класами, як ArrayList, які є більш динамічними. Java хоче в час декларації знати, скільки пам'яті слід виділити для масиву. ArrayList набагато більш динамічний, і розмір його може змінюватися з часом.

Якщо ви ініціалізуєте свій масив довжиною два, а згодом виявиться, що вам потрібна довжина три, вам доведеться викинути те, що у вас є, і створити цілий новий масив. Тому "нове" ключове слово.

У своїх перших двох прикладах ви в момент декларування повідомляєте, скільки пам'яті потрібно виділити. У вашому третьому прикладі ім'я масиву стає вказівником ні на що, і тому при його ініціалізації ви повинні явно створити новий масив, щоб виділити потрібний об'єм пам'яті.

Я б сказав, що (і якщо хтось знає краще, будь ласка, виправте мене) перший приклад

AClass[] array = {object1, object2}

насправді означає

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

але те, що зробили дизайнери Java, - це зробити швидший спосіб написати його, якщо створити масив під час оголошення.

Запропоновані способи подолання хороші. Якщо час або пам'ять є критичними під час виконання, використовуйте масиви. Якщо це не важливо, і ви хочете, щоб код, який простіше зрозуміти та працювати з ним, використовуйте ArrayList.


2
Це ярлик, як ви заявили, цитуючи Oracle: "Крім того, ви можете використовувати синтаксис швидкого доступу для створення та ініціалізації масиву" . Можливо, причина в тому, що масиву потрібно дати деякий простір в пам'яті, використовуючи новий в якийсь момент. Новий неявний в ярлику, але ярлик дійсний лише в декларації. В іншому випадку ярлик не дозволений, а новий обов'язковий.
хвилини

3
Вибачте, але ваша спроба відповісти на питання "чому" не тримає уваги. Компілятор міг би розробити, наскільки великим повинен бути масив, підраховуючи вирази між {і }... так само, як це робиться для дозволених форм ініціалізатора.
Stephen C

8

Я не можу відповісти, чому частина.

Але якщо ви хочете чогось динамічного, то чому б вам не розглянути колекцію ArrayList.

ArrrayList може бути будь-якого типу об'єкта.

І якщо в якості примусу ви хочете його як масив, ви можете використовувати на ньому метод toArray ().

Наприклад:

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

Я сподіваюся, що це може вам допомогти.


2
Не потрібно видавати тип повернення масиву до рядка []. За контрактом повернутий масив має той самий тип, що і вказаний масив. docs.oracle.com/javase/6/docs/api/java/util/…
Ankur Agarwal

4

Для тих із вас, хто не любить цей жахливий new AClass[] { ... }синтаксис, ось трохи цукру:

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

Використовуйте цю маленьку функцію, як вам подобається:

AClass[] array;
...
array = c(object1, object2);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.