Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Герберт Шилдт. Java 2, v5.0 (Tiger). Новые возм...doc
Скачиваний:
5
Добавлен:
01.03.2025
Размер:
1.21 Mб
Скачать

Нельзя создавать объекты, используя параметры типа

Невозможно создать экземпляр класса, задавая его тип с помощью параметра типа. Рассмотрим пример, приведенный в листинге 3.23.

Листинг 3.23. Нельзя с помощью параметра типа T создать объект

class Gen<T> {

T ob;

Gen() {

ob = new T(); // Illegal!!!

}

}

В листинге 3.23 сделана недопустимая попытка создания экземпляра типа T. Причину легко понять: поскольку параметра типа T во время выполнения не существует, как компилятор узнает объект какого типа нужно создать? Напоминаю о том, что в процессе компиляции происходит стирание всех параметров типа.

Ограничения для статических членов класса

Ни один статический член класса не может использовать параметр типа, объявленный этим классом. Все статические члены класса, приведенного в листинге 3.24, недопустимы.

Листинг 3.24. Пример недопустимых членов класса

class Wrong<T> {

// Wrong, no static variables of type T.

static T ob;

// Wrong, no static method can use T.

static T getob() {

return ob;

}

// Wrong, no static method can access Object

// of type T.

static void showob() {

System.out.println(ob);

}

}

Несмотря на то, что нельзя объявить статические члены, использующие параметры типа, объявленные в охватывающем классе, Вы можете объявлять статические настраиваемые методы, которые определяют собственные параметры типа, как было показано ранее в этой главе.

Ограничения для настраиваемого массива

Есть два важных ограничения применения настраиваемых типов, касающиеся массивов. Во-первых, нельзя создать экземпляр массива, у которого базовый тип задан с помощью параметра типа. Во-вторых, Вы не можете создать массив из ссылок на объекты конкретной версии настраиваемого типа. В листинге 3.25 показаны обе ситуации.

Листинг 3.25. Настраиваемые типы и массивы

class Gen<T extends Number> {

T ob;

T vals[]; // OK

Gen(T o, T[] nums) {

ob = o;

// This statement is illegal.

// vals = new T[10]; // can't create an array of T

// But, this statement is OK.

vals = nums; // OK to assign reference to existent array

}

}

class GenArrays {

public static void main(String args[]) {

Integer n[] = { 1, 2, 3, 4, 5 };

Gen<Integer> iOb = new Gen<Integer>(50, n);

// Can't create an array of type-specific generic references.

// Gen<Integer> gens[] = new Gen<Integer>[10]; // Wrong!

// This is OK.

Gen<?> gens[] = new Gen<?>[10]; // OK

}

}

Как показано в листинге 3.25, можно объявить ссылку на массив типа T, такую как в следующей строке:

Т valsU; // OK

Но нельзя создать массив из элементов типа T, подобно попытке, приведенной в следующей помеченной как комментарий строке:

// vals = new T[10]; // не может создать массив из объектов типа Т

Вы не можете создать массив из элементов типа T, потому что параметр T не существует во время выполнения, и у компилятора нет способа узнать, массив из элементов какого типа формировать в действительности.

Тем не менее, можно передать ссылку на совместимый по типу массив в конструктор Gen. о при создании объекта и присвоить эту ссылку переменной vai, как показано в следующей строке:

vals = nums // можно присвоить ссылку существующему массиву

Приведенная строка выполнится, потому что у массива, переданного в класс Gen, известен тип, который в момент создания объекта будет таким же, как параметр типа T.

Внутри метода main() Вы не можете объявить массив ссылок на конкретную версию настраиваемого типа. Следующая строка:

// Gen<Integer> gens[] = new Gen<Integer>[10]; // Неверно!

не будет компилироваться. Массивы из элементов конкретной версии настраиваемого типа просто не разрешены, поскольку могут привести к потере типовой безопасности.

Однако Вы можете создать массив из ссылок на настраиваемый тип, если используете метасимвол, как показано в следующей строке:

Gen<?> gens[] = new Gen<?>[10]; // OK

Такой подход предпочтительней, чем использование массива из элементов несформированного (raw) типа, так как, по крайней мере, какой-то контроль типов будет выполнен.