Эккель Брюс
Шрифт:
Таблица 13.1. Альтернативное обозначение объекта Class с помощью литералов
Литерал
Ссылка на объект Class
boolean.class
Boolean.TYPE
char.class
Character.TYPE
byte.class
Byte.TYPE
short.class
Short.TYPE
int.class
Integer.TYPE
long.class
Long.TYPE
float.class
Float.TYPE
double.class
Double.TYPE
void.class
Void.TYPE
Хотя эти версии эквивалентны, я предпочитаю использовать синтасис .class, так как он лучше сочетается с обычными классами.
Интересно заметить, что создание ссылки на объект Class с использованием записи .class не приводит к автоматической инициализации объекта Class. Подготовка класса к использованию состоит из трех этапов:
• Загрузка — выполняется загрузчиком классов. Последний находит байт-код и создает на его основе объект Class.
• Компоновка — в фазе компоновки проверяется байт-код класса, выделяется память для статических полей, и при необходимости разрешаются все ссылки на классы, созданные этим классом.
• Инициализация — если у класса имеется суперкласс, происходит его инициализация, выполняются статические инициализаторы и блоки статической инициализации.
Инициализация откладывается до первой ссылки на статический метод (конструкторы являются статическими методами) или на неконстантное статическое поле:
//: typeinfo/Class Initialization.java import java util *;
class Initable {
static final int staticFinal = 47; static final int staticFinal2 =
Classlnitialization rand nextlnt(lOOO).
static {
System out рпп^пС'Инициализация Initable"), продолжение &
}
}
class Initable2 {
static int staticNonFinal = 147, static {
System out.рпп^пСИнициализация Initable2"),
}
}
class Initable3 {
static int staticNonFinal = 74. static {
System ои^ргШ1п("Инициализация Initable3").
}
}
public class Classlnitialization {
public static Random rand = new Random(47), public static void main(String[] args) throws Exception { Class initable = Initable class. System out printin("После создания ссылки Initable"). // He приводит к инициализации System out println(Initable.staticFinal). // Приводит к инициализации-System out printin(Initable staticFinal2); // Приводит к инициализации System out println(Initable2 staticNonFinal). Class initable3 = Class forName("Initable3"). System out printlnC"После создания ссылки Initable3"). System out pri ntin(Initable3 staticNonFinal),
}
} /* Output
После создания ссылки Initable 47
Инициализация Initable 258
Инициализация Ini table2 147
Инициализация Initable3 После создания ссылки Ini tablеЗ 74 *///•-
По сути, инициализация откладывается настолько, насколько это возможно. Из результатов видно, что простое использование синтаксиса .class для получения ссылки на класс не приводит к выполнению инициализации. С другой стороны, вызов Class.forNames немедленно инициализирует класс для получения ссылки на Class, как мы видим на примере initable3.
Параметризованные ссылки
Объект Class используется для создания экземпляров класса и содержит полный код методов этих экземпляров. Кроме того, в нем содержатся статические члены класса. Таким образом, ссылка на Class подразумевает точный тип того, на что она указывает — на объект класса Class.
Однако проектировщики Java SE5 решили предоставить возможность уточнения записи посредством ограничения типа объекта Class, на который может указывать ссылка; для этой цели применяется синтаксис параметризации. В следующем примере верны оба варианта синтаксиса:
// typeinfo/GenericClassReferences java
public class GenericClassReferences {
public static void main(String[] args) { Class intClass = int.class, Class<Integer> genericIntClass = int class; genericIntClass = Integer class; // To же самое intClass = double.class,
// genericIntClass = double class; // Недопустимо
}
} ///;-
Если обычная ссылка на класс может быть связана с любым объектом Class, параметризованная ссылка может связываться только с объектами типа, указанного при ее объявлении. Синтаксис параметризации позволяет компилятору выполнить дополнительную проверку типов.