Массивы в Java
Массивы в Java — это структуры данных для хранения нескольких значений одного типа. Похожи на списки в Python, но есть принципиальное отличие, массивы имеют фиксированный размер, нет возможности изменить количество элементов массива после его создания. Кроме того, в массивы все элементы должны быть определенного типа.
Тип массива:
ТИП[]
Получается массив элементов типа ТИП
:
int[] — массив чисел int
byte[] — массив чисел byte
String[] — массив строк
double[] — массив вещественных чисел
int[][] — массив массивов целых чисел
Поэтому, можно заводить переменные с типом массива так:
int[] a;
Способы создания массива:
new ТИП[КОЛИЧЕСТВО]
:new int[10]; // массив из 10 целых new String[3]; // массив из трех строк // создать переменную и назначить ей // массив: int[] a = new int[10];
Массив заполняется нулями (для чисел), 0-символом для char, false для boolean. Если тип объектный (String…), то массив заполняется null (см. далее)
new ТИП[]{перечисление элементов}
:new int[]{10, 20, 30} new String[]{"abc", "xyz"} //создать переменную и назначить массив: int[] a = new int[]{10, 20, 30};
- Предыдущий способ можно сократить, если создание массива происходит при инициализации переменной. Тогда можно не писать
new ТИП[]
. Получится:int[] a = {10, 20, 30}; //это сокращение int[] a = new int[]{10, 20, 30}; //А вот так нельзя: processArray({10, 20, 30}) //можно только: processArray(new int[]{10, 20, 30})
Для обращения к элементу массива используются квадратные скобки, с их помощью можно получить значение или записать его в массив. Индексы начинаются с 0:
int[] a = {10, 20, 30};
sout(a[0]); // получаю 10
sout(a[1]); // получаю 20
sout(a[2]); // получаю 30
sout(a[3]); // ошибка
a[2] = 31;
a[0] = 11;
Выход за границу массива — всегда ошибка ArrayIndexOutOfBoundsException
.
Распечатать массив напрямую не получится: System.out.println(a);
получите что-то типа I]@230BC
. В нем зашифровано, что это массив целых (I = int) (и хэш код объекта).
Надо делать так:
System.out.println(Arrays.toString(a));
Т.е. нужна дополнительная функция Arrays.toString()
, которая превращает массив в строку.
Перебор элементов массива:
Вариант как в python, цикл for в форме “for each”:
for (ПЕРЕМННАЯ : МАССИВ) {
ТЕЛО ЦИКЛА
}
Это аналог for x in a:
в Python. Но при этом переменную можно завести прямо внутри цикла:
int[] a = {10, 20, 30};
for (int x : a)
sout(x); //распечатает 10, потом 20, 30
// x заведена в for, значит, после цикла
// этой переменной больше нет
Или, если при переборе значений массива нужны индексы, или если нужен перебор не по порядку:
(про длину массива ниже)
int[] a = {10, 20, 30};
for (int i = 0; i < a.length; i++)
sout("%d. %d".formatted(i, a[i]));
Получится
0. 10
1. 20
2. 30
Длина массива — это поле “.length” у объекта массива: a.length
. В отличие от строк, после length не нужны скобки. (сравните с "abc".length()
).
Многомерный массив
В Java, как и в Python, отдельных многомерных массивов не существует. Но можно делать массивы массивов. Посмотрим, как это выглядит:
int[][] a = new int[][]{
{10, 20, 30}, // a[0]
{40, 50, 60, 70, 80, 90}, // a[1]
{100, 200} // a[2]
};
sout(Arrays.toString(a[0])); // {10, 20, 30}
sout(Arrays.toString(a[0][1])); // 20
sout(Arrays.toString(a[2])); // {100, 200}
sout(Arrays.toString(a[2][0])); // 100
Как устроен массив a
. a[0]
— это массив {10, 20, 30}
.
Это было создание массива, когда сразу указываются значения внутри массива. Можно создать массив по размеру:
int[][] a = new int[5][6];
Будет создан массив из нулей, потому что, как и раньше, созданный массив заполняется нулями. Первый индекс изменяется от 0 до 4 (5-1), второй — от 0 до 5 (6 - 1). Поэтому a[0]
— это массив из 6 элементов. Получается, что a
— это 5 массивов из 6 элементов каждый.
Разрешается создать массив, указав размер только первого измерения:
int[][] a = new int[5][];
a[0] = new int[]{100, 200, 300};
a[1] = new int[]{11, 22, 33};
a[2] = new int[]{88, 88, 88, 88, 88, 88, 88};
a[3] = new int[]{}; // пустой массив
a[4] = new int[100]; //100 нулей
Это создает массив для пяти массивов. Т.е. в a[0]
, a[1]
, a[2]
, a[3]
, a[4]
можно сохранить массивы чисел.
Обычно, в двумерных массивах считается, что первый индекс — это номер строки, второй — номер столбца.
Т.е. массив a
устроен следующим образом:
100 200 300
11 22 33
88 88 88 88 88 88 88
0 0 0 0 0 0 0 ...
Значение null
В Java есть особое значение null
, которое содержится во всех объектных типах. Например, переменная любого объектного типа (не базового, т.е. String, int[]) может хранить null
. Смысл — отсутствие значения, примерно как None
в Python.
Cо значением null
нельзя совершать действий, кроме как сравнивать (==
) с другими значениями:
String s = null; //нет строки в переменной
int[] a = null; //нет массива (не пустой, а вообще нет)
sout(s.length()); // Ошибка
sout(a.length); // Ошибка
sout(s.equals("")); // Ошибка
sout(s.startsWith("abc")); // Ошибка
if (s != null) // сравниваем с null
sout(s.length()); // так можно, но в данном примере
// это не выполнится
Если какое-то значение может быть null, надо обязательно сначала его проверить на null и только потом использовать. Иначе возможна ошибка NullPointerException.
Пример:
String[] words = new String[10]; // 10 строк
words[0] = "cat";
words[1] = "dog";
for (String word : words)
sout(word.length());
В результате увидим:
3
3
Exception: NullPointerException
Почему? Массив words
перед началом цикла был {"cat", "dog", null, null, null, null, null, null, null, null}
. Поэтому, когда цикл дошел до третьего элемента, случился NullPointerException.