Философия Java3
Шрифт:
И массивы, и контейнеры защищены от возможных злоупотреблений. При выходе за границу массива или контейнера происходит исключение RuntimeException, свидетельствующее об ошибке программиста.
До появления параметризации другим контейнерным классам приходилось работать с объектами так, как если бы они не имели определенного типа. Иначе говоря, объекты рассматривались как принадлежащие к типу Object, корневому для всей иерархии классов в Java. Массивы удобнее «старых» контейнеров тем, что массив создается для хранения конкретного типа. Проверка типов на стадии
Массив может содержать примитивные типы, а «старые» контейнеры — нет. С другой стороны, параметризованные контейнеры могут проверять тип хранимых объектов, а благодаря автоматической упаковке они работают так, как если бы поддерживали хранение примитивов, поскольку преобразование выполняется автоматически. В следующем примере массивы сравниваются с параметризованными контейнерами:
//• arrays/Contai nerComparison.java
import java.util *;
import static net mindview.util Print *;
class BerylliumSphere {
private static long counter,
private final long id = counter++;
public String toStringO { return "Sphere " + id; }
}
public class ContainerComparison {
public static void main(String[] args) {
BerylliumSphere[] spheres = new Beryl 1iumSphere[10]; for(int i =0; i <5; i++)
spheres[i] = new Beryl 1iumSphere, pri nt(Arrays.toStri ng(spheres)); print(spheres[4]);
List<BerylliumSphere> sphereList =
new ArrayLi st<Bery11i umSphere>, for(int i = 0; i < 5, i++)
sphereList add(new BerylliumSphereO); print(sphereList); print(sphereList.get(4));
int[] integers = { 0, 1. 2, 3. 4, 5 }; pri nt(Arrays.toString(integers)), print(integers[4]);
List<Integer> intList = new ArrayList<Integer>(
Arrays asl_ist(0, 1. 2, 3. 4, 5)); intList.add(97); print(intList);
print(intList get(4)): продолжение &
}
} /* Output
[Sphere 0. Sphere 1. Sphere 2. Sphere 3, Sphere 4, null, null, null. null, null] Sphere 4
[Sphere 5. Sphere 6. Sphere 7. Sphere 8. Sphere 9] Sphere 9
[0. 1, 2. 3. 4. 5] 4
[0. 1. 2. 3. 4. 5. 97] 4
*/// ~
Оба способа хранения объектов обеспечивают проверку типов, а единственное очевидное различие заключается в том, что массивы используют для обращения к элементам конструкцию [], a List — методы вроде add или get. Разработчики языка намеренно сделали массивы и ArrayList настолько похожими, чтобы программисту было концептуально проще переключаться между ними. Но, как было показано в главе И, контейнеры обладают более широкими возможностями, чем массивы.
С появлением механизма автоматической упаковки контейнеры по
Массив как объект
С каким бы типом массива вы ни работали, идентификатор массива в действительности представляет собой ссылку на объект, созданный в динамической памяти. Этот объект содержит ссылки на другие объекты и создается либо неявно (в синтаксисе инициализации массива), либо явно конструкцией 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);