public static void main(String[] args) { Creator с = new CreatorO: C.fO;
}
} /* Output: X
*///:-
Массивы параметризованных типов
Как мы видели в Erased.java, создавать массивы параметризованных типов нельзя. Везде, где возникает необходимость в создании таких массивов, следует применять ArrayList:
//: generics/Li stOfGeneri cs.java import java.util.*;
public class ListOfGenerics
private List
public void add(T item) { array.add(item); } public T get(int index) { return array.get(index); } } ///:-
При этом вы получаете поведение массивов с безопасностью типов на стадии компиляции, возможной для параметризации.
Впрочем, иногда бывает нужно создать именно массив параметризованных типов (скажем, во внутренней реализации ArrayList используются массивы). Оказывается, можно переопределить
II: tjenerics/ArrayOfGenericReference.java class Generic
public class ArrayOfGenericReference { static Generic
} ///
Компилятор принимает эту запись без каких-либо предупреждений. С другой стороны, вы не сможете создать массив указанного типа (включая параметры типа), поэтому все это сбивает с толку. Поскольку все массивы обладают одинаковой структурой (размер каждого элемента и способ размещения в памяти) независимо от типа хранящихся данных, создается впечатление, что вы сможете создать массив Object и преобразовать его к нужному типу. Код отком-пилируется, но работать не будет — он выдает исключение ClassCastException:
II: generics/ArrayOfGeneriс.java
public class ArrayOfGeneriс {
static final int SIZE = 100, static Generic
// Компилируется, но приводит к ClassCastException:
//! gia = (Generic
II Тип времени выполнения является "стертым" type:
gia = (Generic
System.out.pri ntin(gi a.getClass().getSi mpleName());
gia[0] = new Generic
//! gia[l] = new ObjectO; II Ошибка компиляции
II Обнаруживается несоответствие типов во время компиляции:
//! gia[2] = new Generic
}
} /* Output:
Generic[]
*///:-
Проблема в том, что массивы отслеживают свой фактический тип, который задается в точке создания массива. Таким образом, даже несмотря на то, что gia преобразуется в Generic
Рассмотрим чуть более сложный пример. Допустим, имеется простая параметризованная «обертка» для массива:
//: generics/GenericArray java
public class GenericArray
array = (T[])new Object[sz];
}
public void put(int index, T item) { array[index] = item;
}
public T get(int index) { return array[index]; } // Метод, предоставляющий доступ к базовому представлению: public T[] rep() { return array; } public static void main(String[] args) { GenericArray
new GenericArray
}
} ///:-
Как и прежде, мы не можем использовать запись Т[] array = new T[sz], поэтому мы создаем массив объектов и преобразуем его.
Метод гер() возвращает Т[]; в методе main() для gai это должен быть тип Integerf], но при попытке вызова и сохранения результата по ссылке на Integer[] будет получено исключение ClassCastException — это снова происходит из-за того, что фактическим типом объекта времени выполнения является Object[]. Если мы немедленно проводим преобразование к Т[], то на стадии компиляции фактический тип массива теряется и компилятор может упустить некоторые потенциальные ошибки. Из-за этого лучше использовать в коллекции Object[], а затем добавить преобразование к Т при использовании элемента массива. Вот как это будет выглядеть в примере GenericArray.java:
//: generics/GenericArray2.java
public class GenericArray2
}