Каноническое имя- typeinfo.toys FancyToy
Имя класса typeinfo toys HasBatteries это интерфейс? [true]
Простое имя HasBatteries
Каноническое имя: typeinfo toys HasBatteries
Имя класса typeinfo toys Waterproof это интерфейс? [true]
Простое имя. Waterproof
Каноническое имя typeinfo toys Waterproof
Имя класса, typeinfo.toys Shoots это интерфейс? [true]
Простое имя: Shoots
Каноническое имя: typeinfo.toys Shoots
Имя класса: typeinfo.toys Toy это интерфейс? [false]
Простое имя: Toy
Каноническое имя typeinfo.toys.Toy *///.-
Класс FancyToy, производный от Toy, реализует несколько интерфейсов: HasBatteries, Waterproof и Shoots. В методе main() создается ссылка на объект Class для класса FancyToy, для этого в подходящем блоке try вызывается метод for-Name(). Обратите внимание на необходимость использования полного имени (с именем пакета) в строке, передаваемой forName().
Метод printInfo() использует getName() для получения полного имени класса и методы getSimpleName() и getCanonicalName() (появившиеся в Java SE5), возвращающие имя без пакета и полное имя соответственно. Метод islnterface() проверяет, представляет ли объект Class интерфейс. Таким образом, по объекту Class можно узнать практически все, что может потребоваться узнать о типе.
Метод Class.getlnterfaces() возвращает массив объектов Class, представляющих интерфейсы, реализованные объектом Class. Метод getSuperclass() возвращает непосредственный (то есть ближайший) базовый класс для объекта Class.
Метод newlnstance() фактически реализует «виртуальный конструктор». Вы как бы говорите: «Я не знаю ваш точный тип, так что создайте себя самостоятельно». В рассмотренном примере ссылка up просто указывает на объект Class, больше никакой информации о типе у вас нет. Поэтому при создании нового экземпляра методом newlnstance() вы получаете ссылку на обобщенный объект Object. Однако полученная ссылка на самом деле указывает на объект Toy. Следовательно, перед посылкой сообщений, характерных для класса Toy, придется провести нисходящее преобразование. Вдобавок объект, созданный с помощью метода newlnstance(), обязан определить конструктор по умолчанию. Позднее в этой главе будет показано, как динамически создать объект класса любым конструктором с использованием механизма
Литералы class
В Java существует еще один способ получения ссылок на объект Class — посредством
FancyToy.class:
Такой способ не только проще, но еще и безопасней, поскольку проверка осуществляется еще во время компиляции. К тому же он не требует вызова forName(), а значит, является более эффективным.
Литералы class работают со всеми обычными классами, так же как и с интерфейсами, массивами и даже с примитивами. Вдобавок во всех классах-обертках для примитивных типов имеется поле с именем TYPE. Это поле содержит ссылку на объект Class для ассоциированного с ним простейшего типа, как показано в табл. 13.1.
Таблица 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. Подготовка класса к использованию состоит из трех этапов:
Инициализация откладывается до первой ссылки на статический метод (конструкторы являются статическими методами) или на неконстантное статическое поле:
//: 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 {