Menu

Массивы в Java: объявление, инициализация, доступ и перебор

Как работают массивы в Java - фиксированная длина, объявление и инициализация, индексация, length, циклы, многомерные массивы и класс-утилита Arrays.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Массив - это список фиксированного размера

Массив в Java хранит фиксированное количество значений одного типа, расположенных по порядку и доступных по позиции. «Фиксированный» - ключевое слово: как только вы создаёте массив, его длина уже никогда не меняется. И «одного типа»: int[] хранит только значения int, String[] хранит только строки. Эта жёсткость - плата за то, что массивы быстры и компактны в памяти.

Тип массива объявляется добавлением [] после типа элемента, после чего вы либо присваиваете литерал, либо выделяете память с помощью new:

Скобки могут стоять после типа (int[] scores) или после имени (int scores[]). Оба варианта компилируются, но int[] scores - идиоматический стиль Java: ставьте [] рядом с типом, где им и место.

Создание массива с помощью new

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

Значения по умолчанию - не случайный мусор: Java инициализирует каждый элемент нулём. Числовые типы начинаются с 0 (или 0.0), boolean начинается с false, а ссылочные типы вроде String начинаются с null. Этот null стоит запомнить: только что выделенный String[] полон null-ов, и вызов метода на одном из них выбрасывает NullPointerException.

Индексация начинается с нуля

Вы читаете и записываете элементы по индексу, отсчитывая от 0. Последний допустимый индекс всегда равен length - 1:

В отличие от массивов в некоторых скриптовых языках, выход за границы не возвращает тихо null или undefined - он выбрасывает исключение. Попробуйте прочитать несуществующий индекс:

Эта программа падает с ошибкой:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3

Это одна из самых частых ошибок новичков. Исправление почти всегда сводится к ошибке на единицу (off-by-one) в условии цикла - использование <= там, где имелось в виду <.

length - это поле, а не метод

Каждый массив хранит свой размер в поле length. Внимание: без круглых скобок.

Вот подвох, на который хоть раз попадается каждый: массивы используют .length (поле), а String использует .length() (метод). Написать nums.length() для массива - ошибка компиляции, как и написать text.length для строки. Одно и то же слово, разные правила - у массива оно без скобок.

Перебор массива

Цикл for-each вы изучили на предыдущей странице, и это самый чистый способ прочитать каждый элемент, когда индекс вам не нужен:

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

Условие - i < names.length, а не <=. Использование <= делает один лишний шаг и выбрасывает исключение выхода за границы из предыдущего раздела. Простое правило: for-each, когда вы только читаете значения, индексный for, когда вам нужна позиция или вы хотите записывать обратно в массив.

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

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

grid[строка][столбец] выбирает одну ячейку. Поскольку каждая строка - это отдельный массив, grid.length - это количество строк, а grid[0].length - количество столбцов в первой строке. Строки даже не обязаны быть одинаковой длины (такое называют зубчатым массивом), хотя большинство сеток прямоугольные.

Класс-утилита Arrays

У самих массивов почти нет методов - их нельзя напрямую отсортировать или с пользой вывести. Для этого Java предоставляет класс-утилиту java.util.Arrays, полный статических помощников:

Несколько моментов, на которые стоит опереться. Arrays.toString(arr) - правильный способ вывести массив: при прямом выводе вы получите бесполезную строку вроде [I@1b6d3586. Arrays.sort сортирует на месте. Arrays.copyOf - это способ «изменить размер»: он возвращает новый массив запрошенной длины, дополняя значениями по умолчанию (две лишние ячейки выше равны 0). А Arrays.binarySearch работает корректно только на уже отсортированном массиве.

Массивы против ArrayList

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

Как только вам нужно свободно добавлять и удалять элементы, массив становится неудобным. Для этого и существует ArrayList - изменяемый, растущий список, который берёт копирование на себя.

Далее: ArrayList

Когда вы не знаете, сколько элементов у вас будет, или это число меняется по ходу работы программы, массив фиксированной длины мешает. ArrayList - ответ Java: список, который растёт и сжимается по требованию, с методами add и remove вместо жонглирования индексами. Об этом - дальше.

Часто задаваемые вопросы

Как объявить и инициализировать массив в Java?

Объявите тип со скобками и присвойте литерал: int[] nums = {1, 2, 3};. Чтобы создать пустой массив фиксированного размера, используйте new: int[] nums = new int[5]; - это даёт 5 ячеек, каждая заполнена значением по умолчанию (0 для int, null для объектов).

Как узнать длину массива в Java?

Используйте поле length (без круглых скобок): nums.length. Это поле, а не метод, поэтому nums.length() - это ошибка компиляции. Обратите внимание: String использует .length() со скобками, а массивы используют .length без них - классическая путаница.

Может ли массив в Java изменить размер после создания?

Нет. Массив в Java имеет фиксированную длину, заданную при создании, и его нельзя ни увеличить, ни уменьшить. Если вам нужен список с изменяемым размером, используйте ArrayList. Чтобы "изменить размер" массива, пришлось бы создать новый, больший, и скопировать в него элементы.

Что такое ArrayIndexOutOfBoundsException в Java?

Это ошибка времени выполнения, которую вы получаете при обращении к несуществующему индексу - меньше 0 или >= array.length. В отличие от некоторых языков, Java не возвращает значение по умолчанию или null при выходе за границы; она выбрасывает исключение. Допустимые индексы всегда идут от 0 до length - 1.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ