1. Массивы в памяти

Картинки в предыдущих примерах немного неточны.

При создании массивов (как и при создании строк) в памяти выделяются два блока памяти: один для хранения самого массива (контейнера), а второй — под переменную, которая хранит его адрес. Уточненная ситуация изображена на картинке ниже:

Массивы в памяти

Зеленым цветом изображен массив на 10 элементов типа int и переменная типа int[], которая хранит адрес (ссылку) массива типа int в памяти.

Для сравнения синим цветом обозначена обычная переменная типа int, которая хранит значение 199.

Чем-то напоминает хранение строк в памяти, не находите?

Верно, строки. И как при работе со строками, «переменные типа массив» можно присваивать друг другу:

Код Пояснение
int[] a = new int[10];
a[2] = 4;
a[7] = 9;
int[] b = a;

a[9] = b[2] + a[7];
Создаем массив на 10 элементов типа int.
В ячейку с индексом 2 записываем значение 4.
В ячейку с индексом 7 записываем значение 9.
В переменную b сохраняем адрес, который есть в переменной a.
Теперь a и b указывают на один и тот же объект-массив в памяти.
В ячейку с индексом 9 объекта-массива записываем сумму значений, которые хранятся в ячейках 2 (хранится 4) и 7 (хранится 9).

При этом объект-массив будет оставаться там, где и был, а переменные a и b будут хранить одинаковые адреса (ссылки) на один и тот же объект. Смотрите картинку:


2. Работа с массивом более детально

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

тип[] имя = new тип[количество];

Где тип — это тип элементов (ячеек) массива, которые мы будем хранить в массиве. Имя — это имя переменой, по которой мы будем к массиву обращаться, а количество — это количество ячеек в массиве.

В примере выше приведена каноническая форма: создание переменной-массива и создание объекта-массива. На самом деле это две независимые конструкции.

Можно создать переменную-массив и объект-массив отдельно:

тип[] имя;
имя = new тип[количество];

И еще один немаловажный момент:

В качестве индекса массива и в качестве количества элементов массива могут выступать переменные и даже целые выражения.

Примеры:

Код Пояснение
int n = 100;
int[] a = new int[n];
Создание массива из n элементов
int n = 100;
int[] a = new int[n * 2 + 3];
Создание массива на 203 элемента
int n = 100;
int[] a = new int[n];
a[n-1] = 2;
a[n-2] = 3;
a[n/5] = a[n-1] + a[n-2]


// a[99] = 2;
// a[98] = 3;
// a[20] = a[99] + a[98];
Важно:
Кстати, обращаем ваше внимание, что если попробовать обратиться к ячейке массива по индексу, которого в массиве нет (в нашем случае это все целые числа, кроме чисел 0..99), программа аварийно завершится с ошибкой ArrayIndexOfBoundException — индекс за границами массива.

3. Длина массива

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

Код Пояснение
int[] array;
if (a < 10)
   array = new int[10];
else
   array = new int[20];
Создаем переменную-массив типа int[]
Если переменная a меньше 10,
то создать массив из 10 элементов.
Иначе
создать массив из 20 элементов

И как работать дальше с таким массивом? Как узнать, сколько в нем элементов?

Для этого у массива есть специальное свойство (переменная) — length. И узнать длину массива можно с помощью такого выражения:

array.length;

Где array — это имя переменной-массива, а length — это имя свойства у объекта-массива. Значение в свойстве length поменять нельзя: само свойство length можно присваивать другим переменным, но ему ничего присваивать нельзя (программа просто не скомпилируется).

Вот как можно продолжить предыдущий пример:

Код Пояснение
int[] array;
if (a < 10)
   array = new int[10];
else
   array = new int[20];
for (int i = 0; i < array.length; i++)
{
   System.out.println(array[i]);
} 
Создаем переменную-массив типа int[]
Если переменная a меньше 10,
то создать массив из 10 элементов.
Иначе
создать массив из 20 элементов
Цикл по всем элементам массива: от 0 и до длины array.length — 1

4. Резюмируем факты о массивах в Java

Давайте резюмируем известные факты о массивах:

Факт 1. Массив состоит из множества ячеек.

Факт 2. Доступ к конкретной ячейке идёт через указание её номера.

Факт 3. Все ячейки одного типа.

Факт 4. Начальное значение для всех ячеек — 0 и null (если в ячейке хранится адрес), false (для типа boolean). Подробнее о значениях по умолчанию вы узнаете в этой лекции.

Факт 5. String[] list – это просто объявление переменной: сам контейнер(объект-массив) еще не создан. Чтобы с ним можно было работать, нужно создать массив (контейнер) и положить его в эту переменную, а потом уже им пользоваться. См. пример ниже.

Факт 6. Когда мы создаём объект-массив (контейнер), нужно указать, какой он длины — сколько в нем ячеек. Это делается командой вида: new TypeName[n];

Факт 7. Длину массива можно узнать через свойство .length.

Факт 8. После создания массива нельзя поменять ни тип его элементов, ни их количество.

Код Пояснение
String s;
String[] list;
s равно null
list равно null
list = new String[10];
int n = list.length;
Переменная list хранит ссылку на объект – массив строк из 10 элементов.
n равно 10
list = new String[0];

Теперь list содержит массив из 0 элементов. Массив есть, но хранить элементы он не может.

list = null;
System.out.println(list[1]);
Будет сгенерировано исключение (ошибка программы) — программа аварийно завершится. list содержит пустую ссылку — null
list = new String[10];
System.out.println(list[10]);
Будет сгенерировано исключение (ошибка программы) — выход за границы массива.
Если list содержит 10 элементов/ячеек, то их разрешённые индексы: 0 1 2 3 4 5 6 7 8 9 — всего 10 штук.