русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Объект Class


Дата добавления: 2015-06-12; просмотров: 792; Нарушение авторских прав


Чтобы понять, как работает RTTI в Java, необходимо знать, каким образом хранится информация о типе во время выполнения программы. Для этой цели используется специальный объект типа Class, который и содержит описание класса. Объект Class используется при создании всех «обыкновенных» объектов любой программы. Каждый класс, задействованный в программе, представлен своим объектом Class. Иначе говоря, при написании и последующей компиляции нового класса для него создается объект Class (который затем сохраняется в одноименном файле с расширением .class). Для создания объекта этого класса виртуальная машина Java JVM), исполняющая программу, использует подсистему, называемую загрузчиком классов. Подсистема загрузчиков классов в действительности состоит из цепочки загрузчиков классов, но только основной загрузчик является частью реализации JVM. Основной загрузчик классов загружает так называемые доверенные классы, в том числе классы Java API, с локального диска. Обычно включать дополнительные загрузчики классов в цепочку не требуется, но в особых ситуациях (например, при загрузке классов для поддержки приложений веб-сервера или при загрузке классов по сети) существует возможность подключения дополнительных загрузчиков. Все классы загружаются в JVM динамически, при первом использовании класса. Таким образом, программа на Java никогда не бывает полностью загружена до начала своего выполнения, и в этом отношении Java отличается от многих традиционных языков. Динамическая загрузка открывает возможности, недоступные или трудно реализуемые в языках со статической загрузкой вроде C++. Сначала JVM проверяет, загружен ли объект Class для этого нового класса. При отрицательном результате JVM ищет подходящий файл .class и подгружает его (а дополнительный загрузчик, например, может подгружать байт-код из базы данных). Загруженный код класса проходит проверку на целостность и на отсутствие некорректного байт-кода Java (одна из «линий защиты» в Java). После того как объект Class для определенного типа будет помещен в память, в дальнейшем он используется при создании всех объектов этого типа. Следующая программа проясняет сказанное:



//: typeinfo/SweetShop.java

// Проверка процесса загрузки классов

import static net.mindview.util.Print.*;

 

class Candy {

static { print("Загрузка класса Candy"); }

}

 

class Gum {

static { print("Загрузка класса Gum"); }

}

 

class Cookie {

static { print("Загрузка класса Cookie"); }

}

 

public class SweetShop {

public static void main(String[] args) {

print("в методе main()");

new Candy();

print("После создания объекта Candy");

try {

Class.forName("Gum");

} catch(ClassNotFoundException e) {

print("Класс Gum не найден");

}

print("После вызова метода Class.forName(\"Gum\")");

new Cookie();

print("После создания объекта Cookie");

}

}

<spoiler text="Output:">

в методе main()

Загрузка класса Candy

После создания объекта Candy

Загрузка класса Gum

После вызова метода Class.forName("Gum")

Загрузка класса Cookie

После создания объекта Cookie

</spoiler> В каждом из классов Candy, Gum и Cookie присутствует статический блок, который отрабатывает один раз, при первой загрузке класса. При выполнении этого блока выводится сообщение, говорящее о том, какой класс загружается. В методе main() создание объектов классов Candy, Gum и Cookie чередуется с выводом на экран вспомогательных сообщений, по которым можно оценить, в какой момент загружается тот или иной класс. Из результата работы программы мы видим, что объект Class загружается только при непосредственной необходимости, а статическая инициализация производится при загрузке этого объекта. Особенно интересно выглядит строка программы

Class.forName("Gum");

Все объекты Class принадлежат классу Class. Объект Class ничем принципиально не отличается от других объектов, поэтому вы можете выполнять операции со ссылкой на него (именно так и поступает загрузчик классов). Один из способов получения ссылки на объект Classзаключается в вызове метода forName(), которому передается строка (String) с именем класса (следите за правильностью написания и регистром символов!). Метод возвращает ссылку на объект Class, которая в данном примере нам не нужна; метод Class.forName()вызывался ради побочного эффекта, то есть загрузки класса Gum, если он еще не в памяти. В процессе загрузки выполняется static-инициализатор класса Gum. Если бы в рассмотренном примере метод Class.forName() сработал неудачно (не смог бы найти класс, который вы хотели загрузить), он возбудил бы исключение ClassNotFoundException. Здесь мы просто сообщаем о проблеме и двигаемся дальше, однако в более совершенной программе можно было бы попытаться исправить ошибку в обработчике исключения. Чтобы использовать информацию RTTI на стадии исполнения, прежде всего необходимо получить ссылку на подходящий объект Class. Один из способов — вызов метода Class.forName() — удобен тем, что вам не потребуется уже сущест­вующий объект нужного типа. Впрочем, если такой объект уже существует, для получения ссылки на его объект Class можно вызвать метод getClass(), определенный в корневом классе Object. Метод возвращает объект Class, представляющий фактический тип объекта. Класс Class содержит немало интересных методов, продемонстрированных в следующем примере:

//: typeinfo/toys/ToyTest.java

// Testing class Class.

package typeinfo.toys;

import static net.mindview.util.Print.*;

 

interface HasBatteries {}

interface Waterproof {}

interface Shoots {}

 

class Toy {

// Закомментируйте следующий далее конструктор по

// умолчанию, тогда в строке с пометкой (*1*)

// возникнет ошибка NoSuchMethodError

Toy() {}

Toy(int i) {}

}

 

class FancyToy extends Toy

implements HasBatteries, Waterproof, Shoots {

FancyToy() { super(1); }

}

 

public class ToyTest {

static void printInfo(Class cc) {

print("Имя класса: " + cc.getName() +

" это интерфейс?[" + cc.isInterface() + "]");

print("Простое имя: " + cc.getSimpleName());

print("Каноническое имя: " + cc.getCanonicalName());

}

public static void main(String[] args) {

Class c = null;

try {

c = Class.forName("typeinfo.toys.FancyToy");

} catch(ClassNotFoundException e) {

print("He найден класс FancyToy");

System.exit(1);

}

printInfo(c);

for(Class face : c.getInterfaces())

printInfo(face);

Class up = c.getSuperclass();

Object obj = null;

try {

// Необходим конструктор по умолчанию:

obj = up.newInstance();

} catch(InstantiationException e) {

print("He удалось создать объект");

System.exit(1);

} catch(IllegalAccessException e) {

print("Нет доступа");

System.exit(1);

}

printInfo(obj.getClass());

}

}

<spoiler text="Output:">

Имя класса typeinfo toys FancyToy это интерфейс? [false]

Простое имя FancyToy

Каноническое имя- 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

</spoiler> Класс FancyToy, производный от Toy, реализует несколько интерфейсов: HasBatteries, Waterproof и Shoots. В методе main() создается ссылка на объект Class для класса FancyToy, для этого в подходящем блоке try вызывается метод forName(). Обратите внимание на необходимость использования полного имени (с именем пакета) в строке, передаваемой forName(). Метод printInfo() использует getName() для получения полного имени класса и методы getSimpleName() и getCanonicalName() (появившиеся в Java SE5), возвращающие имя без пакета и полное имя соответственно. Метод isInterface() проверяет, представляет ли объект Class интерфейс. Таким образом, по объекту Class можно узнать практически все, что может потребоваться узнать о типе. Метод Class.getInterfaces()возвращает массив объектов Class, представляющих интерфейсы, реализованные объектом Class. Метод getSuperclass() возвращает непосредственный (то есть ближайший) базовый класс для объекта Class. Метод newInstance() фактически реализует «виртуальный конструктор». Вы как бы говорите: «Я не знаю ваш точный тип, так что создайте себя самостоятельно». В рассмотренном примере ссылка up просто указывает на объект Class, больше никакой информации о типе у вас нет. Поэтому при создании нового экземпляра методомnewInstance() вы получаете ссылку на обобщенный объект Object. Однако полученная ссылка на самом деле указывает на объект Toy. Следовательно, перед посылкой сообщений, характерных для класса Toy, придется провести нисходящее преобразование. Вдобавок объект, созданный с помощью метода newInstance(), обязан определить конструктор по умолчанию. Позднее в этой главе будет показано, как динамически создать объект класса любым конструктором с использованием механизма рефлексии Java.



<== предыдущая лекция | следующая лекция ==>
Глава 13 ИНФОРМАЦИЯ О ТИПАХ | Литералы class


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.027 сек.