С появлением механизма автоматической упаковки контейнеры по удобству работы с примитивами почти не уступают массивам. Единственным реальным преимуществом массивов остается их эффективность. Впрочем, при решении более общих проблем может оказаться, что возможности массивов слишком ограничены, и тогда приходится пользоваться контейнерными классами.
Массив как объект
С каким бы типом массива вы ни работали, идентификатор массива в действительности представляет собой ссылку на объект, созданный в динамической памяти. Этот объект содержит ссылки на другие объекты и создается либо неявно (в синтаксисе инициализации массива), либо явно конструкцией new. Одной из частей объекта массива (а по сути, единственным доступным полем) является доступная только для чтения переменная length, которая указывает, сколько элементов может храниться в объекте массива. Весь доступ к объекту массива ограничивается синтаксисом [ ].
Следующий пример демонстрирует различные способы инициализации массивов и присваивания ссылок на массивы. Он также наглядно показывает, что массивы объектов и массивы примитивных типов практически идентичны. Единственное различие заключается в том, что массивы объектов содержат ссылки, а массивы примитивов содержат сами примитивные значения.
//• arrays/ArrayOptions.java
// Инициализация и повторное присваивание массивов
import java util.*,
import static net mindview.util Print *;
public class ArrayOptions {
public static void main(String[] args) { // Массивы объектов.
BerylliumSphere[] a. // Локальная неинициализированная переменная BerylliumSphere[] b = new Beryl 11umSphere[5];
// Ссылки в массиве автоматически инициализируются null printC'b. " + Arrays toString(b)). BerylliumSphere[] с = new Beryl 1iumSphere[4], for(int i =0, i < с length, i++)
if(c[i] == null) // Проверка ссылки на действительность [i] = new Beryl 1iumSphere(), // Агрегатная инициализация. BerylliumSphere[] d = { new Beryl 1iumSphere().
new Beryl 1iumSphere(). new BerylliumSphereO
}.
// Динамическая агрегатная инициализация a = new BerylliumSphere[]{
new Beryl liumSphereO. new Beryl liumSphereO.
}.
// (Завершающая запятая не обязательна в обоих случаях)
print("a.length = " + a length);
printC'b.length = " + b length),
printC'c length = " + с length),
printed length = " + d length);
a = d,
print("a.length = " + a.length);
// Массивы примитивов-int[] e, // Ссылка null int[] f = new int[5],
// Примитивы в массиве автоматически инициализируются нулями
printCf. " + Arrays.toString(f)),
int[] g = new int[4];
for(int i = 0. i < g length. i++)
g[i] = i*i. int:: h = { 11, 47, 93 },
// Ошибка компиляции переменная e не инициализирована
//!printC"е length = " + e.length);
printC'f. length = " + f.length),
printC'g length = " + g length),
printC'h length = " + h.length);
e = h,
printC'e.length = " + e length), e = new int[]{ 1.2}, printC'e. length = " + e.length);
}
} /* Output
b [null, null, null, null, null]
a.length = 2
b.length = 5
c. length = 4 d length = 3 a length = 3
f- [0. 0, 0, 0. 0] f length = 5
g.length = 4
h.length = 3 e.length = 3 e length = 2 *///.-
Массив а — неинициализированная локальная переменная, и компилятор не позволяет что-либо делать с этой ссылкой до тех пор, пока она не будет соответствующим образом инициализирована. Массив b инициализируется массивом ссылок на объекты BerylliumSpere, хотя ни один такой объект в массив не заносится. Несмотря на это, мы можем запросить размер массива, потому что b указывает на действительный объект. В этом проявляется некоторый недостаток массивов: поле length сообщает, сколько элементов
Массив с демонстрирует создание массива с последующим присваиванием объектов BerylliumSphere всем элементам массива. Массив d демонстрирует синтаксис «агрегатной инициализации», при котором объект массива создается (с ключевым словом new, как массив с)
Следующую конструкцию инициализации массива можно назвать «динамической агрегатной инициализацией». Агрегатная инициализация, используемая d, должна использоваться в точке определения d, но при втором синтаксисе объект массива может создаваться и использоваться в любой точке. Предположим, методу hide() передается массив объектов BerylliumSphere. Его вызов может выглядеть так:
hide(d);
однако массив, передаваемый в аргументе, также можно создать динамически:
hide(new BerylliumSphere[]{ new Beryl 1iumSphere(). new BerylliumSphereО });
Во многих ситуациях такой синтаксис оказывается более удобным.
Выражение
a=d;