Вход на хостинг
IT-новости
20.04.2016 iPhone 2017 года поместят в водонепроницаемый корпус из стекла
Линейка iPhone в новом году серьезно поменяется. В этом уверен аналитический исследователь Мин Чи Ку......
30.07.2015 Ищем уникальный контент для сайта
Ищем уникальный контент для сайта Без уникального контента Ваш сайт обречен на то, что его страницы......
На самом деле, с точки зрения Java, класс TestModule, возникающий в результате прямого вызова «TestModule testModule= ...» в тексте файла Test.java, и класс TestModule, полученный вызовом:
Class.forName("TestModule",true,loader)
– это два совершенно разных класса. Первый был загружен системным загрузчиком (вместе с самым главным классом Test), а второй – одним из экземпляров нашего загрузчика DynamicClassOverloader. По классическим законам объектно-ориентированного программирования приведение типов между ними невозможно.
Более того, каждая итерация нашего цикла, оказывается, порождала новую версию класса TestModule, не связанную с предыдущими. В этом можно убедиться следующим образом. Модифицируем класс TestModule:
public class TestModule {
private static int counter= 0;
public String toString() {
return "TestModule, version 1! "+(counter++);
}
}
В нормальных условиях каждое новое обращение к методу toString() такого класса привело бы к получению строки с новым, увеличенным на 1 значением счетчика counter. Если бы в тесте Test.java был обычный вызов Class.forName(«TestModule»), мы бы это и увидели: на каждой итерации цикла распечатывались бы разные значения счетчика. А с нашим загрузчиком мы все время будем видеть нулевое значение. Каждое пересоздание экземпляра загрузчика DynamicClassOverloader приводит к появлению нового пространства имен, в котором инициализируется совершенно новая версия класса TestModule, ничего не знающая о предыдущих версиях и о содержащихся в них статических переменных.
Фактически, мы придали языку Java новое свойство – «динамичность» классов. Теперь, обращаясь прямо или косвенно к любому классу, придется думать о том, какая именно версия этого класса будет использована и можно ли ее использовать совместно с тем классом, который к ней обращается.
Свойство, что и говорить, крайне неудобное. Как же теперь работать с «динамическими» классами? Ведь все версии классов, которыми пользуется наш первый класс, загруженный DynamicClassOverloader, и которые тем самым тоже загружены нашим загрузчиком, – все эти версии неизвестны в пространстве имен стационарной части – в нашем случае в главном классе Test.
Решение этой проблемы – заблокировать свойство «динамичности» для некоторых классов, т.е. потребовать, чтобы такие классы наш загрузчик загружал стандартным способом – через вызов «findSystemClass(name)». Назовем такие классы «истинно-статическими» – «true-static». Такие «true-static»-классы можно будет свободно совместно использовать в стационарной части программы и всех версиях «динамических» классов. Для «true-static»-классов всегда будет существовать только одна версия, как и предполагается в обычном языке Java, и не будет проблем несоответствия типа. Можно, например, сделать «true-static» все ключевые интерфейсы, основные типы данных, которые должны получать и возвращать «динамические» классы, базовые типы исключений, подлежащие перехвату и единообразной обработке, и т. п.