Нельзя создавать объекты, используя параметры типа
Невозможно создать экземпляр класса, задавая его тип с помощью параметра типа. Рассмотрим пример, приведенный в листинге 3.23.
Листинг 3.23. Нельзя с помощью параметра типа T создать объект
class Gen {
T ob;
Gen() {
ob = new T(); // Illegal!!!
}
}
В листинге 3.23 сделана недопустимая попытка создания экземпляра типа T. Причину легко понять: поскольку параметра типа T во время выполнения не существует, как компилятор узнает объект какого типа нужно создать? Напоминаю о том, что в процессе компиляции происходит стирание всех параметров типа.
Ограничения для статических членов класса
Ни один статический член класса не может использовать параметр типа, объявленный этим классом. Все статические члены класса, приведенного в листинге 3.24, недопустимы.
Листинг 3.24. Пример недопустимых членов класса
class Wrong {
// 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 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 iOb = new Gen(50, n);
// Can't create an array of type-specific generic references.
// Gen gens[] = new Gen[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 gens[] = new Gen[10]; // Неверно!
не будет компилироваться. Массивы из элементов конкретной версии настраиваемого типа просто не разрешены, поскольку могут привести к потере типовой безопасности.
Однако Вы можете создать массив из ссылок на настраиваемый тип, если используете метасимвол, как показано в следующей строке:
Gen> gens[] = new Gen>[10]; // OK
Такой подход предпочтительней, чем использование массива из элементов несформированного (raw) типа, так как, по крайней мере, какой-то контроль типов будет выполнен.
Ограничение настраиваемых исключений
Настраиваемый класс не может расширять класс Throwable. Это означает, что у Вас нет возможности создавать настраиваемые классы исключений.
Заключительные замечания
Настраиваемые типы — мощное расширение языка Java, потому что они упрощают создание повторно используемого кода, обладающего типовой безопасностью. Несмотря на то, что, на первый взгляд, синтаксис настраиваемых типов может показаться несколько устрашающим, он станет Вашей второй натурой, после того, как Вы поработаете с ним какое-то время. Откровенно говоря, код с применением настраиваемых типов — это неотъемлемая часть будущего всех программистов, пишущих на языке Java
|