Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Класс Class (уже описанный в этой главе) поддерживает концепцию рефлексии (reflection), для которой существует дополнительная библиотека java. lang. reflect, состоящая из классов Field, Method и Constructor (каждый реализует интерфейс Member). Объекты этих классов создаются JVM, чтобы представлять соответствующие члены неизвестного класса. Объекты Constructor используются для создания новых объектов класса, методы get и set — для чтения и записи значений полей класса, представленных объектами Field, метод invoke — для вызова метода, представленного объектом Method. Вдобавок в классе Class имеются удобные методы getFields, getMethods

и getConstruc-tors, которые возвращают массивы таких объектов, как поля класса, его методы и конструкторы. (За подробной информацией обращайтесь к описанию класса Class в электронной документации JDK.) Таким образом, информация о неизвестном объекте становится доступной прямо во время выполнения программы, а потребность в ее получении ко времени компиляции программы отпадает.

Важно понимать, что в механизме рефлексии нет ничего сверхъестественного. Когда вы используете рефлексию для работы с объектом неизвестного типа, виртуальная машина JVM рассматривает его и видит, что он принадлежит определенному классу (это делает и обычное RTTI), но, перед тем как проводить с ним некоторые действия, необходимо загрузить соответствующий объект Class. Таким образом, файл .class для класса этого объекта должен быть доступен JVM либо в сети, либо в локальной системе. Таким образом, истинное различие между традиционным RTTI и рефлексией состоит в том, что при использовании RTTI файл .class открывается и анализируется компилятором. Другими словами, вы можете вызывать методы объекта «нормальным» способом. При использовании рефлексии файл .class во время компиляции недоступен; он открывается и обрабатывается системой выполнения.

Извлечение информации о методах класса

Рефлексия редко используется напрямую; она существует в языке в основном для поддержки других возможностей, таких как сериализация объектов и компоненты JavaBeans. Однако существуют ситуации, в которых динамическая информация о классе просто незаменима.

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

//: typeinfo/ShowMethods.java

// Использование рефлексии для вывода полного списка методов

// класс, в том числе и определенных в базовом классе.

// {Args: ShowMethods}

import java.lang.reflect.*;

import java.util.regex.*;

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

public class ShowMethods {

private static String usage = "usage:\n" +

"ShowMethods qualified.class.name\n" + "To show all methods in class or:\n" + "ShowMethods qualified.class.name word\n" + "To search for methods involving 'word'"; private static Pattern p = Pattern.compile("\\w+\\."); public static void main(String[] args) { if(args.length < 1) { print(usage);

System exit(O);

}

int lines = 0; try {

Class<?> с = Class.forName(args[0]); Method[] methods = c.getMethods; Constructor[] ctors = c.getConstructorsO; if(args.length == 1) {

for(Method method . methods) print(

p.matcher(method.toStri ng).replaceAl

1С"));

for(Constructor ctor • ctors)

pri nt(p.matcher(ctor.toStri ng).replaceAl1("")

);

lines = methods.length + ctors.length,

} else {

for(Method method : methods)

if (method. toStringO. indexOf(args[l]) != -1) { print(

p.matcher(method.toStri ng

О)

replaceAll (""));

lines++;

}

for(Constructor ctor : ctors)

if(ctor.toStringO.indexOf(args[l]) != -1) { print(p.matcher(

ctor.toStri ng О).replaceAl 1 ("

lines++;

}

}

} catch(ClassNotFoundException e) {

print("No such class: " + e):

}

}

} /* Output:

public static void main(String[]) public native int hashCodeO public final native Class getClassO

public final void wait(long.int) throws InterruptedException public final void waitO throws InterruptedException public final native void wait(long) throws InterruptedException public boolean equals(Object) public String toStringO public final native void notifyО public final native void notifyAllO public ShowMethodsO *///:-

Методы класса Class getMethods и getConstructors возвращают массивы объектов Method и Constructor, которые представляют методы и конструкторы класса. В каждом из этих классов есть методы для получения и анализа имен, аргументов и возвращаемых значений представляемых методов и конструкторов. Впрочем, также можно использовать простой метод toString, как и сделано здесь, чтобы получить строку с полным именем метода. Остальная часть кода разбирает командную строку и определяет, подходит ли определенное выражение образцу для поиска (с использованием indexOf), а после выделяет описатели имен классов.

Результат, полученный от Class.forName, не может быть известен во время компиляции, поэтому вся информация о сигнатуре методов становится доступной во время выполнения. Если вы тщательно изучите документацию по рефлексии из JDK, то увидите, что рефлексия позволяет установить необходимые аргументы и вызвать метод объекта, «абсолютно неизвестного» во время компиляции программы (чуть позже будут приведены соответствующие примеры). Скорее всего, вам эти возможности никогда не понадобятся, но сам факт их существования интересен.

Приведенный выше результат был получен из командной строки

java ShowMethods ShowMethods

На экран выводится открытый (public) конструктор по умолчанию, хотя в тексте программы такой конструктор не определяется. Тот конструктор, что имеется теперь в классе, автоматически сгенерирован компилятором. Если вы после этого сделаете класс ShowMethods не открытым (удалите из его определения спецификатор доступа public, то есть предоставите ему доступ в пределах пакета), сгенерированный компилятором конструктор исчезнет из списка методов. Сгенерированный конструктор имеет тот же уровень доступа, что и его класс.

Также интересно запустить программу в виде

java ShowMethods java lang String

с передачей дополнительного параметра char, int, String и т. п.

Эта программа сэкономит вам немало времени при программировании, когда вы будете мучительно вспоминать, есть ли у этого класса определенный метод, если вам потребуется узнать, имеются ли у некоторого класса методы, возвращающие объекты Color, и т. д.

Динамические посредники

«Посредник» (proxy) принадлежит к числу основных паттернов проектирования. Он представляет собой объект, который подставляется на место «настоящего» объекта для расширения или модификации его операций. Приведу тривиальный пример, показывающий структуру посредника:

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5