Массивы. Альтернативный синтаксис объявления java array

Массивы (arrays) _ это упорядоченные наборы элементов одного типа. Элементами массива могут служить объекты простых и ссылочных типов, в том Числе и ссылки на другие массивы. Массивы сами по себе являются объектами и

наследуют класс Object. Объявление

int ia = new int;

Определяет массив с именем ia, который изначально указывает на набор из трех Элементов типа int.

В объявлении массива его размерность не указывается. Количество элементов массива задается при его создании посредством оператора new. Длина массива фиксируется в момент создания и в дальнейшем изменению не поддается. Впрочем, переменной типа массива (в нашем примере – ia) в любой момент может быть поставлен в соответствие новый массив с другой размерностью.

Доступ к элементам массива осуществляется по значениям их номеров-индексов.

Первый элемент массива имеет индекс, равный нулю (0), а последний – length – 1. Обращение к элементу массива выполняется посредством задания имени массива и значения индекса, заключенного в квадратные скобки, [ и ]. в предыдущем примере первым элементом массива ia будет ia, а последним – ia. При каждом обращении к элементу массива по индексу исполняющая система Java проверяет, находится ли значение индекса в допустимых пределах, и генерирует исключение типа ArraylndexOutOfBoundsException, если результат проверки ложен. 6 Выражение индекса должно относиться к типу int – только этим и ограничивается максимальное количество элементов массива.

Длину массива легко определить с помощью поля length объекта массива (которое неявно снабжено признаками publiс и final). Ниже приведен дополненный код прежнего примера, в котором предусмотрено выполнение Цикла, обеспечивающего вывод на экран содержимого каждого элемента массива ia:

for (int i = о; i < ia.length; i++)

system.out.println(i + ": " + ia[i]);

Массив нулевой длины (т.е. такой, в котором нет элементов) принято называть пустым. Обратите внимание, что ссылка на массив, равная значению null, и ссылка на пустой массив – это совершенно разные вещи. Пустой массив это реальный массив, в котором попросту отсутствуют элементы. Пустой массив представляет собой удобную альтернативу значению null при возврате из метода. Если метод способен возвращать null, прикладной код, в котором выполняется обращение к методу, должен сравнить возвращенное значение с null прежде, чем перейти к выполнению оставшихся операций. Если же метод возвращает массив (возможно, пустой), никакие дополнительные проверки не нужны – разумеется, помимо тех, которые касаются длины массива и должны выполняться в любом случае.

Допускается и иная форма объявления массива, в которой квадратные скобки задаются после идентификатора массива, а не после наименования его типа:

int ia = new int;

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

Модификаторы в объявлениях массивов

Правила употребления в объявлениях массивов тех или иных модификаторов обычны и зависят только от того, к какой категории относится массив – к полям или Локальным переменным. Существует единственная особенность, которую важно помнить, – модификаторы применяются к массиву как таковому, но не к его отдельным элементам. Если в объявлении массива указан признак final, это значит только то, что ссылка на массив не может быть изменена после его создания, но никак не запрещает возможность изменения содержимого отдельных элементов массива. Язык не позволяет задавать каких бы то ни было модификаторов (скажем, final или уоlatilе) для элементов массива.

Многомерные массивы

В Java поддерживается возможность объявления многомерных массивов (multidimensional arrays) (т.е. массивов, элементами которых служат другие массивы), Код, предусматривающий объявление двумерной матрицы и вывод на экран содержимого ее элементов, может выглядеть, например, так:

float mat = new float;

setupMatrix(mat);

for (int у = о; у < mat.length; у++) {

for (int х = о; х < mat[y].length; х++)

system.out.print(mat[y][x] + " ");

system.out.println();

При создании массива должна быть указана, по меньшей мере, его первая, "самая левая", размерность. Другие размерности разрешается не задавать – в этом случае их придется определить позже. Указание в операторе new единовременно всех размерностей – это самый лаконичный способ создания массива, позволяющий избежать необходимости использования дополнительных операторов new. Выражение объявления и создания массива mat, приведенное выше, равнозначно следующему фрагменту кода:

float mat = new float;

for (int у = о; у < mat.length; у++)

mat[y] = new float;

Такая форма объявления обладает тем преимуществом, что позволяет наряду с получением массивов с одинаковыми размерностями (скажем, 4 х 4) строить и массивы массивов различных размерностей, необходимых для хранения тех или иных последовательностей данных.

Инициализация массивов

При создании массива каждый его элемент получает значение, предусмотренное по умолчанию и зависящее от типа массива: нуль (0) – для числовых типов, ‘\u0000′ _ для char, false – для boolean и null – для ссылочных типов. Объявляя массив ссылочного типа, мы на самом деле определяем массив переменных этого типа. Рассмотрим следующий фрагмент кода:

Attr attrs = new Attr;

for (int i = о; i < attrs.length; i++)

attrs[i] = new Attr(names[i], values[i]);

После выполнения первого выражения, содержащего оператор new, переменная attrs получит ссылку на массив из 12 переменных, которые инициализированы значением null, Объекты Attr как таковые будут созданы только в процессе про хождения цикла.

Массив может инициализироваться (одновременно с объявлением) посредством конструкции в фигурных скобках, в которой перечислены исходные Значения его элементов:

String dangers = { "Львы", "Тигры", "Медведи" };

Следующий фрагмент кода даст тот же результат:

String dangers = new String; dangers = "Львы";

dangers = "Тигры";

dangers = "Медведи";

Первая форма, предусматривающая задание списка инициализаторов в фигурных скобках, не требует явного использования оператора new – он вызывается косвенно исполняющей системой. Длина массива в этом случае определяется Количеством значений-инициализаторов. Допускается и возможность явного задания оператора new, но размерность все равно следует опускать она, как и раньше, определяется исполняющей системой:

String dangers = new String { "Львы", "Тигры", "Медведи" };

Подобную форму объявления и инициализации массива разрешается применять в любом месте кода, например в выражении вызова метода:

printStringsCnew String { "раз", "два", "три" });

Массив без названия, который создается таким образом, называют анонимным (anonymous).

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

int pascalsTriangle = {

{ 1, 4, 6, 4, 1 },

Индексы многомерных массивов следуют в порядке от внешнего к внутренним. Так, например, pascalsTriangle; // Массив из 5 элементов double ar2 = {3.14, 2.71, 0, -2.5, 99.123}; // Массив из 6 элементов типа double То есть при создании массива мы можем указать его размер, либо сразу перечислить через запятую все желаемые элементы в фигурных скобках (при этом размер будет вычислен автоматически на основе той последовательности элементов, которая будет указана). Обратите внимание, что в данном случае после закрывающей фигурной скобки ставится точка с запятой, чего не бывает когда это скобка закрывает какой-то блок.

Если массив был создан с помощью оператора new , то каждый его элемент получает значение по умолчанию. Каким оно будет определяется на основании типа данных (0 для int, 0.0 для double и т. д.).

Объявить имя для массива и создать сам массив можно было на одной строке по следующей схеме: тип имя = new тип[размер]; тип имя = {эл0, эл1, …, элN}; Примеры: int mas1 = {10,20,30}; int mas2 = new int;

Чтобы обратиться к какому-то из элементов массива для того, чтобы прочитать или изменить его значение, нужно указать имя массива и за ним индекс элемента в квадратных скобках. Элемент массива с конкретным индексом ведёт себя также, как переменная. Например, чтобы вывести последний элемент массива mas1 мы должны написать в программе:

System.out.println("Последний элемент массива " + mas1);

А вот так мы можем положить в массив mas2 тот же набор значений, что хранится в mas1:

Mas2 = 10; mas2 = 20; mas2 = 30;Уже из этого примера видно, что для того, чтоб обратиться ко всем элементам массива, нам приходится повторять однотипные действия. Как вы помните для многократного повторения операций используются циклы. Соответственно, мы могли бы заполнить массив нужными элементами с помощью цикла: for(int i=0; iПонятно, что если бы массив у нас был не из 3, а из 100 элементов, до без цикла мы бы просто не справились.

Длину любого созданного массива не обязательно запоминать, потому что имеется свойство, которое его хранит. Обратиться к этому свойству можно дописав.length к имени массива. Например:

Int razmer = mas1.length; Это свойство нельзя изменять (т. е. ему нельзя ничего присваивать), можно только читать. Используя это свойство можно писать программный код для обработки массива даже не зная его конкретного размера.

Например, так можно вывести на экран элементы любого массива с именем ar2:

For(int i = 0; i <= ar2.length - 1; i++) { System.out.print(ar2[i] + " "); } Для краткости удобнее менять нестрогое неравенство на строгое, тогда не нужно будет вычитать единицу из размера массива. Давайте заполним массив целыми числами от 0 до 9 и выведем его на экран: for(int i = 0; i < ar1.length; i++) {ar1[i] = Math.floor(Math.random() * 10); System.out.print(ar1[i] + " "); }

Обратите внимание, на каждом шаге цикла мы сначала отправляли случайное значение в элемент массива с i-ым индексом, а потом этот же элемент выводили на экран. Но два процесса (наполнения и вывода) можно было проделать и в разных циклах. Например:

For(int i = 0; i < ar1.length; i++) { ar1[i] = Math.floor(Math.random() * 9); } for(int i = 0; i < ar1.length; i++) { System.out.print(ar1[i] + " "); } В данном случае более рационален первый способ (один проход по массиву вместо двух), но не всегда возможно выполнить требуемые действия в одном цикле.

Для обработки массивов всегда используются циклы типа «n раз» (for) потому, что нам заранее известно сколько раз должен повториться цикл (столько же раз, сколько элементов в массиве).

Задачи

    Создайте массив из всех чётных чисел от 2 до 20 и выведите элементы массива на экран сначала в строку, отделяя один элемент от другого пробелом, а затем в столбик (отделяя один элемент от другого началом новой строки). Перед созданием массива подумайте, какого он будет размера.

    2 4 6 … 18 20
    2
    4
    6

    20

    Создайте массив из всех нечётных чисел от 1 до 99, выведите его на экран в строку, а затем этот же массив выведите на экран тоже в строку, но в обратном порядке (99 97 95 93 … 7 5 3 1).

    Создайте массив из 15 случайных целых чисел из отрезка . Выведите массив на экран. Подсчитайте сколько в массиве чётных элементов и выведете это количество на экран на отдельной строке.

    Создайте массив из 8 случайных целых чисел из отрезка . Выведите массив на экран в строку. Замените каждый элемент с нечётным индексом на ноль. Снова выведете массив на экран на отдельной строке.

    Создайте 2 массива из 5 случайных целых чисел из отрезка каждый, выведите массивы на экран в двух отдельных строках. Посчитайте среднее арифметическое элементов каждого массива и сообщите, для какого из массивов это значение оказалось больше (либо сообщите, что их средние арифметические равны).

    Создайте массив из 4 случайных целых чисел из отрезка , выведите его на экран в строку. Определить и вывести на экран сообщение о том, является ли массив строго возрастающей последовательностью.

    Создайте массив из 20-ти первых чисел Фибоначчи и выведите его на экран. Напоминаем, что первый и второй члены последовательности равны единицам, а каждый следующий - сумме двух предыдущих.

    Создайте массив из 12 случайных целых чисел из отрезка [-15;15]. Определите какой элемент является в этом массиве максимальным и сообщите индекс его последнего вхождения в массив.

    Создайте два массива из 10 целых случайных чисел из отрезка и третий массив из 10 действительных чисел. Каждый элемент с i-ым индексом третьего массива должен равняться отношению элемента из первого массива с i-ым индексом к элементу из второго массива с i-ым индексом. Вывести все три массива на экран (каждый на отдельной строке), затем вывести количество целых элементов в третьем массиве.

    Создайте массив из 11 случайных целых чисел из отрезка [-1;1], выведите массив на экран в строку. Определите какой элемент встречается в массиве чаще всего и выведите об этом сообщение на экран. Если два каких-то элемента встречаются одинаковое количество раз, то не выводите ничего.

    Пользователь должен указать с клавиатуры чётное положительное число, а программа должна создать массив указанного размера из случайных целых чисел из [-5;5] и вывести его на экран в строку. После этого программа должна определить и сообщить пользователю о том, сумма модулей какой половины массива больше: левой или правой, либо сообщить, что эти суммы модулей равны. Если пользователь введёт неподходящее число, то программа должна требовать повторного ввода до тех пор, пока не будет указано корректное значение.

    Программа должна создать массив из 12 случайных целых чисел из отрезка [-10;10] таким образом, чтобы отрицательных и положительных элементов там было поровну и не было нулей. При этом порядок следования элементов должен быть случаен (т. е. не подходит вариант, когда в массиве постоянно выпадает сначала 6 положительных, а потом 6 отрицательных чисел или же когда элементы постоянно чередуются через один и пр.). Вывести полученный массив на экран.

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

Сортировка массива

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

Сортировка выбором

Рассмотрим пример сортировки по возрастанию. То есть на начальной позиции в массиве должен стоять минимальный элемент, на следующей - больший или равный и т. д., на последнем месте должен стоять наибольший элемент.Суть алгоритма такова. Во всём отыскиваем минимальный элемент, меняем его местами с начальным. Затем в оставшейся части массива (т. е. среди всех элементов кроме начального) снова отыскиваем минимальный элемент, меняем его местами уже со вторым элементом в массиве. И так далее.

Иллюстрация:

For (int i = 0; i

Сортировка методом пузырька

Суть алгоритма такова. Если пройдёмся по любому массиву установив правильный порядок в каждой паре соседних элементов, то после того прохода на последнем месте массива гарантированно будет стоять нужный элемент (самый большой для сортировки по возрастанию или самый маленький для сортировки по убыванию). Если ещё раз пройтись по массиву с такими же преобразованиями, то и на предпоследнем месте гарантированно окажется нужный элемент. И так далее.Пример:

2 9 1 4 3 5 2 → порядок правильный, не будет перестановки

2 9 1 4 3 5 2 → 2 1 9 4 3 5 2

2 1 9 4 3 5 2 → 2 1 4 9 3 5 2

2 1 4 9 3 5 2 → 2 1 4 3 9 5 2

2 1 4 3 9 5 2 → 2 1 4 3 5 9 2

2 1 4 3 5 9 2 → 2 1 4 3 5 2 9

Код: /* Внешний цикл постоянно сужает фрагмент массива, * который будет рассматриваться, ведь после каждого прохода * внутреннего цикла на последнем месте фрагмента будет * оказываться нужный элемент (его не надо рассматривать снова). */ for (int i = a.length - 1; i >= 2; i--) { /* В переменной sorted мы будем хранить признак того, * отсортирован ли массив. Перед каждым проходом внутреннего * цкла будем предполагать, что отсортирован, но если совершим * хоть одну перестановку, то значит ещё не конца отсортирован. * Этот приём, упрощающий сортировку, называется критерием Айверсона. */ boolean sorted = true; /* Во внутреннем цикле мы проходимся по фрагменту массива, который * определяется внешним циклом. В этом фрагменте мы устанавливаем * правильный порядок между соседними элементами, так попарно * обрабатывая весь фрагмент. */ for (int j = 0; j a) { int temp = a[j]; a[j] = a; a = temp; sorted = false; } } /* Если массив отсортирован (т.е. не было ни одной перестановки * во внутреннем цикле, значит можно прекращать работу внешнего * цикла. */ if(sorted) { break; } }

Многомерные массивы

Массив может состоять не только из элементов какого-то встроенного типа (int, double и пр.), но и, в том числе, из объектов какого-то существующего класса и даже из других массивов.

Массив который в качестве своих элементов содержит другие массивы называется многомерным массивом.Чаще всего используются двумерные массивы. Такие массивы можно легко представить в виде матрицы. Каждая строка которой является обычным одномерным массивом, а объединение всех строк - двумерным массивом в каждом элементе которого хранится ссылка на какую-то строку матрицы.Трёхмерный массив можно представить себе как набор матриц, каждую из которых мы записали на библиотечной карточке. Тогда чтобы добраться до конкретного числа сначала нужно указать номер карточки (первый индекс трёхмерного массива), потому указать номер строки (второй индекс массива) и только затем номер элемент в строке (третий индекс).

Соответственно, для того, чтобы обратиться к элементу n-мерного массива нужно указать n индексов.

Объявляются массивы так: int d1; //Обычный, одномерный int d2; //Двумерный double d3; //Трёхмерный int d5; //Пятимерный При создании массива можно указать явно размер каждого его уровня: d2 = int; // Матрица из 3 строк и 4 столбцов Но можно указать только размер первого уровня: int dd2 = int; /* Матрица из 5 строк. Сколько элементов будет в каждой строке пока не известно. */ В последнем случае, можно создать двумерный массив, который не будет являться матрицей из-за того, что в каждой его строке будет разное количество элементов. Например: for(int i=0; i<5; i++) { dd2[i] = new int; } В результате получим такой вот массив: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Мы могли создать массив явно указав его элементы. Например так: int ddd2 = {{1,2}, {1,2,3,4,5}, {1,2,3}};

При этом можно обратиться к элементу с индексом 4 во второй строке ddd2 , но если мы обратимся к элементу ddd2 или ddd2 - произойдёт ошибка, поскольку таких элементов просто нет. Притом ошибка это будет происходить уже во время исполнения программы (т. е. компилятор её не увидит).

Обычно всё же используются двумерные массивы с равным количеством элементов в каждой строке.Для обработки двумерных массивов используются два вложенных друг в друга цикла с разными счётчиками.Пример (заполняем двумерный массив случайными числами от 0 до 9 и выводим его на жкран в виде матрицы): int da = new int; for(int i=0; i

Задачи

    Создать двумерный массив из 8 строк по 5 столбцов в каждой из случайных целых чисел из отрезка . Вывести массив на экран.

    Создать двумерный массив из 5 строк по 8 столбцов в каждой из случайных целых чисел из отрезка [-99;99]. Вывести массив на экран. После на отдельной строке вывести на экран значение максимального элемента этого массива (его индекс не имеет значения).

    Cоздать двумерный массив из 7 строк по 4 столбца в каждой из случайных целых чисел из отрезка [-5;5]. Вывести массив на экран. Определить и вывести на экран индекс строки с наибольшим по модулю произведением элементов. Если таких строк несколько, то вывести индекс первой встретившейся из них.

    Создать двумерный массив из 6 строк по 7 столбцов в каждой из случайных целых чисел из отрезка . Вывести массив на экран. Преобразовать массив таким образом, чтобы на первом месте в каждой строке стоял её наибольший элемент. При этом изменять состав массива нельзя, а можно только переставлять элементы в рамках одной строки. Порядок остальных элементов строки не важен (т.е. можно соврешить только одну перестановку, а можно отсортировать по убыванию каждую строку). Вывести преобразованный массив на экран.

    Для проверки остаточных знаний учеников после летних каникул, учитель младших классов решил начинать каждый урок с того, чтобы задавать каждому ученику пример из таблицы умножения, но в классе 15 человек, а примеры среди них не должны повторяться. В помощь учителю напишите программу, которая будет выводить на экран 15 случайных примеров из таблицы умножения (от 2*2 до 9*9, потому что задания по умножению на 1 и на 10 - слишком просты). При этом среди 15 примеров не должно быть повторяющихся (примеры 2*3 и 3*2 и им подобные пары считать повторяющимися).

2010, Алексей Николаевич Костин. Кафедра ТИДМ математического факультета МПГУ.

В языке Java присутствуют массивы. Эти массивы типизированы. Декларация

Point myPoints;

описывает переменную myPointsкак массив объектов типаPoint. Завести массив определенного размера можно с помощью инструкции вида

myPoints = new Point;

Значения элементов массива при этом устанавливаются равными специальной величине null.

Размер массива может быть получен во время выполнения программы:

howMany = myPoints.length;

Для создания массива вы можете пользоваться квадратными скобками, расположив их справа от имени массива или от типа объектов, из которых составлен массив, например:

int nAnotherNumbers;

Допустимы оба варианта, поэтому вы можете выбрать тот, который вам больше нравится.

При определении массивов в языке Java нельзя указывать их размер. Приведенные выше две строки не вызывают резервирования памяти для массива. Здесь просто создаются ссылки на массивы, которые без инициализации использовать нельзя.

Для того чтобы заказать память для массива, вы должны создать соответствующие объекты с помощью ключевого слова new, например:

int nAnotherNumbers;

nAnotherNumbers = new int;

Как выполнить инициализацию ячеек таблицы?

Такую инициализацию можно выполнить либо статически, либо динамически. В первом случае вы просто перечисляете значения в фигурных скобках, как это показано ниже:

int nColorRed = {255, 255, 100, 0, 10};

Динамическая инициализация выполняется с использованием индекса массива, например, в цикле:

int nInitialValue = 7;

int nAnotherNumbers;

nAnotherNumbers = new int;

for(int i = 0; i < 15; i++)

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

Массивы могут быть многомерными и, что интересно, несимметричными.

Ниже создается массив массивов. В нулевом и первом элементе создается массив из четырех чисел, а во втором - из восьми:

int nDim = new int;

nDim = new int ;

nDim = new int ;

nDim = new int ;

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

Массивы в языке Java являются объектами некоторого встроенного класса. Для этого класса существует возможность определить размер массива, обратившись к элементу данных класса с именем length, например:

int nAnotherNumbers;

nAnotherNumbers = new int;

for(int i = 0; i < nAnotherNumbers.length; i++)

nAnotherNumbers[i] = nInitialValue;

Для определения размера массива вам не нужен такой оператор, как sizeof из языка программирования С, потому что существует другой способ определения этого размера.

Других структурных типов (не являющихся объектами) в языке Java нет, то есть нет структур, объединений и т.п. Нет в Java и указателей.

Строки символов являются объектами типа String(текстовые константы) илиStringBuffer(изменяемые строки). Пример:

String hello = "Hello world!";


Учеба на "Разработчика игр" + трудоустройство

Java массивы

Массив - это структура данных, в которой хранятся величины одинакового типа. Доступ к отдельному элементу массива осуществляется с помощью целого индекса. Например, если а - массив целых чисел, то значение выражения а [ i ] равно i-му целому числу в массиве.

Массив объявляется следующим образом: сначала указывается тип массива, т.е тип элементов, содержащихся в массиве, за которым ставится пара пустых квадратных скобок, а затем - имя переменной. Например, вот как объявляется массив, состоящий из целых чисел:
int a;

Однако этот оператор лишь объявляет переменную а, не инициализируя ее настоящим массивом. Чтобы создать массив, нужно применить оператор new.

Этот оператор создает массив, состоящий из 100 целых чисел. Элементы этого массива нумеруются от 0 до 99 (а не от 1 до 100). После создания массив можно заполнять, например, с помощью цикла.

int а = new int;
for (int i = 0; i < 100; i++)
a[i] = i; // Заполняет массив числами от 0 до 99.

Если вы попытаетесь обратиться к элементу а (или любому другому элементу, индекс которого выходит за пределы диапазона от 0 до 99), создав массив, состоящий из 100 элементов, программа прекратит работу, поскольку возникнет исключительная ситуация, связанная с выходом индекса массива за пределы допустимого диапазона.
Чтобы подсчитать количество элементов в массиве, используйте метод имяМасси-
ва.length.

Например,

for (int i = 0; i < a. length; i++ System.out.println (a[i]);

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

Массив можно объявить двумя способами:

int a;
или
int a;

Большинство программистов на языке Java предпочитают первый стиль, поскольку в нем четче отделяется тип массива int (целочисленный массив) от имени переменной.

Инициализаторы массивов и безымянные массивы

В языке Java есть средство для одновременного создания массива и его инициализации. Вот пример такой синтаксической конструкции:

int smallPrimes = { 2, 3, 5, 7, 11, 13};

Отметим, что в этом случае не нужно применять оператор new. Кроме того, можно даже инициализировать безымянный массив:

new int { 16, 19, 23 , 29 , 31, 37}

Это выражение выделяет память для нового массива и заполняет его числами, указанными в фигурных скобках. При этом подсчитывается их количество и, соответственно, определяется размер массива. Эту синтаксическую конструкцию удобно применять для повторной инициализации массива без образования новой переменной. Например, выражение

smallPrimes = new int{ 17, 19, 23, 29, 31, 37 };
представляет собой укороченную запись выражения
int anonymous = { 17, 19, 23, 29, 31, 37 };
smailPrimes = anonymous;

Можно создать массив нулевого размера. Такой массив может оказаться полезным при написании метода, вычисляющего некий массив, который оказывается пустым. Массив нулевой длины объявляется следующим образом:

new типЭлементов

Заметим, что такой массив не эквивалентен объекту null.

Копирование массивов

Один массив можно скопировать в другой, но при этом обе переменные будут ссылаться на один и тот же массив.

int luckyNumbers = smailPrimes;
luckyNuimbers = 12; // Теперь элемент smailPrimesтакже равен 12.

Результат показан на рис. 3.14. Если необходимо скопировать все элементы одного массива в другой, следует использовать метод arraycopy из класса System. Его вызов выглядит следующим образом:

System.arraycopy(from, fromlndex, to, tolndex, count);

Массив to должен иметь достаточный размер, чтобы в нем поместились все копируемые элементы.

Рис. 3.14. Копирование массива

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

int smailPrimes = {2, 3, 5, 7, 11, 13};
int luckyNumbers = {1001, 1002, 1003, 1004, 1005, 1006, 1007};
System.аггаусору(smailPrimes, 2, luckyNumbers, 3, 4);
for (int i = 0; i < luckyNumbers.length; i++)
System.println(i +.": " + luckyNumbersfi]);

Выполнение этих операторов приводит к следующему результату.

0: 1001
1: 1002
2: 1003
3: 5
4: 7
5: 11
6: 13

Рис. 3.15. Копирование элементов массива

Массив в языке Java значительно отличается от массива в языке C++. Однако он практически совпадает с указателем на динамический массив. Это значит, что оператор

int a = new int; //Java
эквивалентен оператору
i n t * = new i n t [ 1 0 0 ] ; // C++,
а не
int a; // C++

В языке Java оператор no умолчанию проверяет диапазон изменения индексов. Кроме того, в языке Java нет арифметики указателей - нельзя увеличить указатель а, чтобы обратиться к следующему элементу массива.

Эту статью я решил написать по следам одной дискуссии в форуме. Она будет посвящена массивам в Java. Честно сказать, мне не удается припомнить какой-либо книги, где этот вопрос был бы освещен четко и внятно. Между тем, массивы в Java серьезно отличаются от массивов в любом другом языке, которые я когда-либо видел. И знание этих отличий весьма и весьма необходимо.

Статья разделена на три части:

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

Итак, начнем мы с простейших случаев, а именно –

Одномерные массивы примитивных типов

Эти массивы практически не отличаются от того, к чему привыкли программисты, использующие другие языки. Создание массива производится с помощью все того же оператора new:

// creating array of integers with 5 elements: int array = new int ;

В отличие от других языков, правда, в Java есть пара приятных мелочей. Первое – размер массива может быть запрошен явно, через свойство.length:

int array = new int ; System.out.println("Array size: "+array.length); // will print: Array size: 5

Свойство это является final , потому выставить через него новый размер массива, увы, не получится.

Вторая мелочь – контроль выхода за границы массива. Это делает интерпретатор, в случае выхода индекса за пределы массива будет инициировано исключение java.lang.ArrayIndexOutOfBoundsException . Перехватывать его не обязательно, и, я бы даже сказал, нежелательно, т.к. это RuntimeException и сигнализирует оно о том, что программа работает неправильно. И уж совсем не стоит проектировать приложение в расчете на то, что после прохождения всего массива будет брошено это исключение, и это будет сигналом к завершению цикла обработки. Это очень плохая идея.

После создания массив инициализируется значением по умолчанию для типа его элементов. Это гарантируется спецификацией языка.

Есть одна тонкость. При создании размер массива может быть задан равным 0 . Это будет вполне полноценный массив, содержащий 0 элементов. Его свойство.length равно 0. Такая конструкция временами оказывается весьма полезной.

Пара слов о копировании. Тривиальный способ – создать массив такого же размера и в цикле перенести содержимое. Хорошо, надежно, но не очень быстро. Есть способ быстрее – использовать метод System.arraycopy(...) . В этом методе после всех проверок происходит просто копирование области памяти. Сигнатура этого метода такая:

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

Копирование происходит из массива src , начиная с позиции srcPos , в массив dest , начиная с позиции destPos . Всего копируется length элементов. Обратите внимание, что src и dest имеют тип Object . Это сделано для того, чтобы этот метод мог обрабатывать массивы любого типа. Если src или dest не является массивом, будет инициировано исключение java.lang.ArrayStoreException .

Собственно, о массивах примитивных типов сказать больше нечего. Потому плавно переходим к следующему разделу:

Одномерные массивы объектов

Бо льшая часть из того, что сказано о массивах примитивных типов, верна и для массивов объектов. Их размер может быть получен через.length , выход за границы контролируется. Создаются они через оператор new:

// array of java.awt.Point with 10 elements: java.awt.Point points = new java.awt.Point;

Заметьте, вызова конструктора тут НЕТ. java.awt.Point после оператора new указывает лишь на тип элементов создаваемого массива.

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

А хранятся в этом массиве не объекты. Там хранятся ссылки на них. Как любая переменная объектного типа является ссылкой на объект, так и любой элемент массива тоже является ссылкой. А для ссылки значение по умолчанию – null !

Эта ошибка чуть ли не классическая. Очень часто приходится встречать вопросы "откуда тут берется NullPointerException " по отношению к коду следующего вида:

Java.awt.Point points = new java.awt.Point; points.x = 1; // <-- here is a NullPointerException

Теперь, думаю, понятно, откуда берется эта ошибка. Массив создан и его элементы инициализированы значением null . Однако сами объекты не созданы. Ситуация в точности аналогична использованию переменной со значением null . Правильный фрагмент выглядит так:

Java.awt.Point points = new java.awt.Point; for (int i=0; inew java.awt.Point(); } // now you can use array points.x = 1; // <-- NO NullPointerException here!

Хочу специально коснуться вопроса копирования элементов массива объектов. Поскольку содержит он ссылки, именно они и копируются. Т.е. после копирования новый массив будет указывать на тот же самый набор объектов! И если изменить внутреннее состояние какого-либо из объектов – это будет видно при доступе к нему через любой из массивов.

Итак, мы потихоньку подобрались к самому интересному разделу –

Многомерные массивы

Это наиболее отличающийся от других языков класс массивов. Честно говоря, такого я нигде больше не видел. Для простоты начнем с двумерных массивов, а потом уже перейдем к n-мерным.

Прежде всего хочу упомянуть такой факт. Для двумерного массива не существует такого понятия как его размеры. Можно определить размер массива только по первому индексу. Причина кроется в организации массива. Он представляет собой массив ссылок на массивы, каждый из которых содержит реальные данные. И эти массивы могут иметь разную длину!

Рассмотрим вот этот двумерный массив. Его длина по первому индексу равна 3 . Ее можно получить через a.length . Элементами этого массива являются ссылки на массивы с данными. Длина каждого из этих массивов может быть получена так же через.length . Доступ к каждому из этих массивов осуществляется через его индекс – первый индекс в массиве a .

Думаю, теперь понятно, что можно говорить только о длине двумерного массива по первому индексу. Максимальное значение второго индекса может быть получено только для каждого конкретного значения первого индекса.

// 2d array of ints with 10 rows of 5 elements each int array2d = new int;

Эта конструкция создает двумерный массив размером 10х5 . О размерах тут можно говорить только потому, что размер по второму индексу явно указан при инициализации. И все строки будут длины 5, массив будет прямоугольным.

Есть, однако, и другой способ. Для примера создадим массив, приведенный выше на рисунке:

int a = new int ; // line 1 a = new int ; // line 2 a = new int ; // line 3 a = new int ; // line 4

Обратите внимание, в строке 1 при инициализации массива не указана размерность по второму индексу!

Что происходит в этом коде? В строке 1 создается массив по первому индексу, размером 3 . Это означает, что выделяется память под три ссылки на массивы-строки. Сами массивы не создаются, выделенная память инициализирована значениями null .

В строке 2 создается массив длиной 2 . Ссылка на этот массив сохраняется в первом элементе массива по первому индексу. Точно так же в строках 3 и 4 создаются массивы, ссылки на которые сохраняются во втором и третьем элементах массива по первому индексу.

В итоге мы имеем массив произвольной формы. Разумеется, мы могли бы создать все три массива-строки одинаковой длины, скажем, 5 . Эти действия были бы полностью эквивалентны конструкции new int .

Стоит упомянуть еще раз, что ситуация при создании массивов-строк с типом объектов в точности та же, что и для одномерных массивов (коими они, собственно, и являются). Под ссылки на объекты выделяется память, но сами объекты не создаются.

Перейдем теперь к n-мерным массивам. Ничего нового тут нет. Как двумерный массив представляет собой массив ссылок на одномерные массивы, так и трехмерный массив представляет собой список ссылок, но уже на двумерные массивы. Общее правило таково:

N-мерный массив является одномерным массивом, элементами которого являются ссылки на массивы размерности N-1.

Соответственно, N-мерные массивы можно создавать одним выражением, с использованием оператора new и указанием размеров по всем измерениям. А можно и последовательно – создать массив, указав размерность по одному или нескольким индексам, а оставшиеся неинициализированными ссылки проинициализировать вручную, создавая массивы нужной мерности, но произвольного размера/формы. Однако для массивов большой мерности это довольно сложная задача, на мой взгляд. Собственно, как и вообще работа с многомерными массивами.

Отдельно несколько слов о копировании многомерных массивов с помощью System.arraycopy . Массивы будут копироваться ТОЛЬКО по первому индексу. Иначе говоря, во второй массив будут перенесены ссылки на массивы размерности N-1 из первого массива. В случае двумерного массива – это ссылки на массивы-строки. Это обстоятельство весьма облегчает копирование массивов, скажем, при добавлении новой строки – память нужно выделять только под массив по первому индексу. Далее ссылки на все строки будут скопированны в новый массив, а последняя ссылка, которая должна указывать на новую строку, будет проинициализирована вручную:

int initArray; // initial array int newArrayLength = initArray.length+1; int newArray = new int ; for (int i=0; inew int [];

Как я уже упоминал, System.arraycopy делает то же самое, что и приведенный выше цикл, только быстрее.

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

Всем спасибо! Надеюсь, кому-то эта информация оказалась полезной и интересной.