Синтаксис инициализации массива, когда он не указан в объявлении

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 или более.
Mat
другая проблема заключается в том, что в вставленном коде были символы TAB. Это портит форматирование.
Stephen C
Оки, спасибо, eclipse использует вкладки в отступах, поэтому, когда я копирую и вставляю, это все портит. спасибо за редактирование
Джейсон Роджерс
Eclipse можно и нужно перенастроить, чтобы не использовать символы TAB для отступов. Пожалуйста, не используйте это как оправдание.
Stephen C

Ответы:

138

Почему это заблокировано Java?

Спросите у Java-дизайнеров. Для ограничения может быть какая-то тонкая грамматическая причина. Обратите внимание, что некоторые конструкции создания / инициализации массивов отсутствовали в Java 1.0, а (IIRC) были добавлены в Java 1.1.

Но «почему» несущественно ... ограничение есть, и с ним нужно жить.

Я знаю, как это обойти, но время от времени было бы проще.

Вы можете написать это:

AClass[] array;
...
array = new AClass[]{object1, object2};
Стивен С
источник
9
без нового объявления не было бы никакой разницы между блоком операторов и инициализатором массива (как в javascript, что может вводить в заблуждение}
bestsss
10
Это было бы толк ... и трудно разобрать. Подумайте, {o1()}было ли правильное выражение {o1();}допустимым блоком операторов. Парсер должен добраться до '}' или ';' прежде чем он сможет различить два случая. Грамматический вопрос совсем не тонкий !!
Stephen C
19

Я попытаюсь ответить на вопрос, почему: массив Java очень прост и рудиментарен по сравнению с классами, такими как ArrayList, которые более динамичны. Java хочет знать во время объявления, сколько памяти следует выделить для массива. ArrayList намного более динамичен, и его размер может меняться со временем.

Если вы инициализируете свой массив длиной два, а позже выясняется, что вам нужна длина трех, вам придется выбросить то, что у вас есть, и создать совершенно новый массив. Поэтому ключевое слово «новое».

В ваших первых двух примерах вы указываете во время объявления, сколько памяти нужно выделить. В вашем третьем примере имя массива становится указателем вообще ни на что, и поэтому, когда он инициализируется, вы должны явно создать новый массив, чтобы выделить правильный объем памяти.

Я бы сказал, что (и если кто-то знает лучше, поправьте меня) первый пример

AClass[] array = {object1, object2}

на самом деле означает

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

но разработчики Java сделали более быстрый способ его записи, если вы создадите массив во время объявления.

Предлагаемые обходные пути хороши. Если использование времени или памяти критично во время выполнения, используйте массивы. Если это не критично, и вам нужен код, который легче понять и с которым работать, используйте ArrayList.

продвигать
источник
2
Это ярлык, как вы заявили, цитируя Oracle: «В качестве альтернативы вы можете использовать сокращенный синтаксис для создания и инициализации массива» . Причина может быть в том, что в какой-то момент массиву нужно предоставить некоторое пространство в памяти, используя new. New неявно присутствует в ярлыке, но ярлык действителен только в объявлении. В других местах ярлык не разрешен, а новое является обязательным.
мин
3
Извините, но ваша попытка ответить на вопрос "почему" не выдерживает критики. Компилятор сможет определить, насколько большим должен быть массив, подсчитав выражения между {и }... точно так же, как это делается для разрешенных форм инициализатора.
Stephen C
8

Я не могу ответить, почему.

Но если вам нужно что-то динамическое, почему бы вам не рассмотреть Collection ArrayList.

ArrrayList может быть любого типа объекта.

И если в качестве принуждения вы хотите, чтобы он был массивом, вы можете использовать для него метод toArray ().

Например:

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

Надеюсь, это может вам помочь.

Amanpreet
источник
2
Нет необходимости приводить возвращаемый тип массива к String []. По контракту возвращаемый массив имеет тот же тип, что и указанный массив. docs.oracle.com/javase/6/docs/api/java/util/…
Агарвал,
4

Для тех из вас, кому не нравится этот чудовищный new AClass[] { ... }синтаксис, вот немного сахара:

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

Используйте эту маленькую функцию как хотите:

AClass[] array;
...
array = c(object1, object2);
user123
источник