Массивы в Java
Объявляйте, инициализируйте и обращайтесь к элементам массивов в Java — фиксированных последовательностей значений одного типа.
Массив в Java — это контейнер фиксированного размера, который хранит последовательность значений одного типа. После создания его длина не изменяется, и каждая ячейка может хранить ровно одно значение — int, String, ссылку на любой объект, всё что соответствует объявленному типу.
Массивы — это основа, на которой построены остальные коллекции Java (ArrayList, HashMap и другие). Они менее удобны в использовании, чем эти высокоуровневые классы, но быстры, предсказуемы и встречаются повсюду: в аргументах методов, возвращаемых значениях, производительном коде.
Объявление массива
Тип массива — это тип элемента, за которым следуют []:
int[] scores; // an array of ints
String[] names; // an array of String references
double[] prices; // an array of doublesКвадратные скобки можно также ставить после имени переменной — int scores[]; — но форма int[] scores используется гораздо чаще, и именно её следует применять.
Объявление переменной ещё не создаёт массив; оно лишь даёт Java ячейку, которая может хранить ссылку на него. Поначалу ячейка содержит null.
Создание массива с помощью new
Чтобы действительно выделить память под массив, используйте new с указанием длины:
int[] scores = new int[5];Это резервирует место для 5 значений типа int. Java инициализирует каждую ячейку значением по умолчанию для данного типа:
- числовые типы →
0(или0.0) boolean→falsechar→'�'(нулевой символ, кодовая точка 0 — не пробел)- ссылочные типы →
null
Таким образом, scores сразу содержит {0, 0, 0, 0, 0}. Состояния «неинициализированного» значения не существует — после создания массива каждая позиция имеет определённое значение.
Литералы массива
Если содержимое известно заранее, используйте литерал:
int[] scores = {90, 85, 73, 100, 62};
String[] colors = {"red", "green", "blue"};Длина выводится из числа элементов. Такая форма допустима только в той же строке, что и объявление — позже написать scores = {90, 85}; нельзя. Для этого используйте явную форму:
scores = new int[]{90, 85, 73, 100, 62};Доступ к элементам
Элементы читаются и записываются по нулевому индексу с помощью квадратных скобок:
int[] scores = {90, 85, 73, 100, 62};
System.out.println(scores[0]); // 90
System.out.println(scores[4]); // 62
scores[2] = 80; // replace 73 with 80Допустимые индексы — от 0 до length - 1. Индекс за пределами диапазона бросает ArrayIndexOutOfBoundsException во время выполнения — Java не возвращает значение по умолчанию и не переходит к началу.
Свойство length
У каждого массива есть публичное поле length, доступное только для чтения, которое сообщает его размер:
int[] scores = {90, 85, 73, 100, 62};
System.out.println(scores.length); // 5Обратите внимание: это поле, а не метод — без скобок. Это одна из маленьких особенностей Java: у строк .length(), у массивов .length. От коллекций они тоже отличаются (list.size()). Формы легко перепутать; компилятор подскажет.
length фиксируется при создании. Чтобы «увеличить» массив, нужно выделить новый и скопировать данные — см. главу Копирование массивов.
Массивы хранят ссылки, а не копии
Когда тип элемента является объектом, массив хранит ссылки, а не сами объекты:
String[] colors = {"red", "green", "blue"};
String first = colors[0];
// first and colors[0] both reference the same "red" stringДля примитивов это различие не важно — значения int копируются при записи и чтении. Для объектов изменение элемента извне массива влияет на то, что видит массив, поскольку они используют общую ссылку.
Значения по умолчанию и null-массивы
Объявленная, но не присвоенная переменная массива равна null, и обращение к .length или любому индексу бросает NullPointerException:
int[] data; // not initialized
// System.out.println(data.length); // would throw NullPointerException
data = new int[3];
System.out.println(data.length); // 3Пустой массив — с длиной ноль — это вполне корректный массив, и обычно именно его следует возвращать в качестве «пустого» результата, а не null:
int[] none = new int[0];
System.out.println(none.length); // 0Рабочий пример
Вывод массива
Распространённый сюрприз: передача массива напрямую в System.out.println не показывает его содержимое. Вместо этого выводятся тип массива и хэш его идентичности:
int[] scores = {90, 85, 73};
System.out.println(scores); // e.g. [I@39ed3c8d — not the values![I означает «массив int», а шестнадцатеричная часть — это хэш идентичности, а не данные. Чтобы увидеть элементы, используйте Arrays.toString из пакета java.util:
import java.util.Arrays;
int[] scores = {90, 85, 73};
System.out.println(Arrays.toString(scores)); // [90, 85, 73]Для вложенных (многомерных) массивов используйте Arrays.deepToString.
Что дальше
Вы умеете создавать массив и обращаться к его элементам по индексу. Следующий шаг — итерация: обход каждого элемента с помощью циклов по массиву, чтобы не писать scores[0], scores[1], scores[2] вручную один за другим.