Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Для ссыпки на объект используйте его интерфейс



 

В статье 25 дается совет: в качестве типа параметра указывать интерфейс, а не класс. В более общей формулировке: ссылаясь на объект, вы должны отдавать пред­почтение не классу, а интерфейсу. Если есть подходящие типы интерфейсов, то параметры, возвращаемые значения, переменные и поля следует декларировать, указывая интерфейс. Единственный случай, когда вам нужно ссылаться на класс объекта,- при его создании. Для пояснения рассмотрим случай с классом Vector, ко­торый является реализацией интерфейса List. Возьмите за правило писать так

 

// Хорошо: указывается тип интерфейса.

List subscribers = new Vector();

 

а не так:

// Плохо: в качестве типа указан класс!

Vector subscribers = new Vector();

 

Если вы выработаете привычку указывать в качестве типа интерфейс, ваша про грамма будет более гибкой. Когда вы решите поменять реализацию, все, что для этого потребуется,- изменить название класса в конструкторе (или использовать другой статической метод генерации). Например, первую из представленных деклара­ций можно переписать следующим образом:

 

List subscribers = new ArrayList();

 

И весь окружающий код сможет продолжить работу. Код, окружающий эту деклара­цию, ничего не знал о прежнем типе, который реализовывал интерфейс. Поэтому он не должен заметить подмену декларации.

Однако нельзя упускать из виду следующее: если первоначальная реализация интерфейса выполняла некие особые функции, не предусмотренные общими согла­шениями для этого интерфейса, и программный код зависел от этих функций, крайне важно, чтобы новая реализация интерфейса обеспечивала те же функции. Например, если программный код, окружавший первую декларацию, зависел от того обстоятель­ства, что Vector синхронизирован по отношению к потокам, то замена класса Vector на ArrayList будет некорректной.

 

 

145

 

 

Есть лишь несколько сложных приложений, которым необходим механизм отра­жения. В их число входят визуализаторы классов, инспекторы объектов, анализаторы программного кода и интерпретирующие встроенные системы. Отражение можно также использовать в системах вызова удаленных процедур (RPC system) с целью снижения потребности в компиляторах запросов. Если у вас есть сомнения, подпадает ли ваше приложение в одну из этих категорий, вероятнее всего, оно к ним не относится.

Вы можете без больших затрат использовать многие преимущества механиз­ма отражения, если будете применять его в усеченном виде. Во многих програм­мах, которым нужен класс, отсутствовавший на момент компиляции, для ссылки на него можно использовать соответствующий интерфейс или суперкласс (статья 34). Если это то, что вам нужно, вы можете сначала опосредованно создать экземпляры, а затем обращаться к ним обычным образом. используя их интерфейс или супер­класс. Если соответствующий конструктор, как часто бывает, не имеет параметров, вам даже не нужно обращаться к пакету java.lang.ref1ect - требуемые функции предоставит метод C1ass. newlnstance.

В качестве примера приведем программу, которая создает экземпляр интерфейса Set, чей класс задан первым аргументом командной строки. Остальные аргументы командной строки программа вставляет в полученный набор и затем распечатывает его. При выводе аргументов программа уничтожает дубликаты (первый аргумент игнорируется). Порядок печати аргументов зависит от того, какой класс указан в первом аргументе. Если вы указываете "java.util.HashSet", аргументы выводятся в произвольном порядке, если - "java.uti1.TreeSet", они печатаются в алфавитном порядке, поскольку элементы в наборе TreeSet сортируются.

 

// Опосредованное создание экземпляра с доступом

public static void main(String[] args) {

// Преобразует имя класса в экземпляр класса

Class сl = null;

try {

сl =Class.forName(args[0]); }

catch(ClassNotFoundException е) {

System.err.println("Class not found.”);      // Класс не найден

System. exi t (1) ; }

 

// Создает экземпляр класса

Sets = null;

try {

s = (Set) cl.newlnstance();

catch(IllegalAccessExceptlon е) {

System.err.println("Class not accessible. ");   // Доступ к классу невозможен System.exit(1);

 

 

148

 

} catch(InstantiationException е) {

System.err.println("Class not instantiable."); // Класс не позволяет создать экземпляр System.exit(1); }

// Проверяет набор

s.addAll(Arrays.asList(args).subList(1, args.length-1));

 System.out.println(s); }

 

Хотя эта программа является всего лишь игрушкой, она показывает мощный прием. Этот код легко превратить в универсальную программу про верки наборов, которая проверяет правильность указанной реализации Set, активно воздействуя на один или несколько экземпляров и выясняя, выполняют ли они соглашения для интерфейса Set. Точно так же его можно превратить в универсальный инструмент для анализа произ­водительности. Методика, которую демонстрирует эта программа, в действительности достаточна для создания полноценной инфраструктуры с предоставлением услуг (service provider framework) (статья 1). В большинстве случаев описанный прием ­это все, что нужно знать об отражении классов.

Этот пример иллюстрирует два недостатка системы отражения. Во-первых, во время его выполнения могут возникнуть три ошибки, которые, если бы не использовался механизм отражения, были бы обнаружены еще на стадии компиляции. Во-вторых, Для генерации экземпляра класса по его имени потребовалось Двадцать строк кода, тогда как вызов конструктора уложился бы ровно в одну строку. Эти недостатки, однако, касаются лишь той части программы, которая создает объект как экземпляр класса. Как только экземпляр создан, он неотличим от любого другого экземпляра Set. Благодаря этому значительная часть кода в реальной программе не поменяется от локального применения механизма отражения.

Приемлемым, хотя и редким вариантом использования отражения является раз­рушение зависимости класса от других классов, методов и полей, которые в момент выполнения могут отсутствовать, Это может пригодиться при написании пакета, ко­торый должен работать с различными версиями какого-либо другого пакета. Прием заключается в том, чтобы компилировать наш пакет для работы в минимальном окружении (обычно это поддержка самой старой версии), а доступ ко всем новым классам и методам осуществлять через механизм отражения. Чтобы это работало, необходимо Предпринимать правильные действия, когда в ходе выполнения программы обнаружится, что тот или иной новый класс или метод, к которому вы пытаетесь получить доступ, в данный момент отсутствует. Эти действия могут заключаться в применении каких-либо альтернативных средств, позволяющих достичь той же цели, или же в использовании усеченного функционала.

Подведем итоги. Отражение - это мощный инструмент, который необходим для решения определенных сложных задач системного программирования. Однако у него

 

149

 

 

есть много недостатков. Если вы пишите программу, которая должна работать с клас­сами, неизвестными на момент компиляции, то вы должны по возможности использо­вать механизм отражения только для создания экземпляров отсутствовавших классов, а для доступа к полученным объектам следует применять некий интерфейс или супер­класс, который известен уже на стадии компиляции.

 


Поделиться:



Последнее изменение этой страницы: 2019-04-11; Просмотров: 206; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.014 с.)
Главная | Случайная страница | Обратная связь