Эккель Брюс
Шрифт:
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) принадлежит к числу основных паттернов проектирования. Он представляет собой объект, который подставляется на место «настоящего» объекта для расширения или модификации его операций. Приведу тривиальный пример, показывающий структуру посредника:
//. typeinfo/SimpleProxyDemo java import static net mindview.util Print *,
interface Interface { void doSomethingO; void somethingElse(String arg).
}
class Real Object implements Interface {
public void doSomethingO { printC'doSomething"); } public void somethingElse(String arg) { printC'somethingElse " + arg),
}
}
class SimpleProxy implements Interface { private Interface proxied, public SimpleProxy(Interface proxied) { this.proxied = proxied,
}
public void doSomethingO {
print("SimpleProxy doSomething"), proxied doSomethingO,
}
public void somethingElse(String arg) {
print("SimpleProxy somethingElse " + arg); proxied.somethingElse(arg);
}
class SimpleProxyDemo {
public static void consumer^Interface iface) { iface doSomethingO; iface somethingElseC'bonobo");
}
public static void main(String[] args) { consumer(new RealObjectO), consumer(new SimpleProxy(new RealObjectO)),