Class, поля и методы
Поля, методы и конструкторы тоже представлены объектами
Получив Class<?>, можно исследовать членов типа.
Для этого Reflection использует отдельные объекты: Field для поля,
Method для метода и Constructor<?> для конструктора.
Они описывают структуру члена: имя, тип, параметры, модификаторы и доступные аннотации.
for (Method method : String.class.getDeclaredMethods()) {
System.out.println(method.getName());
}
Здесь программа не вызывает методы String, а получает их описания и читает имена.
Тот же подход работает с полями и конструкторами.
get... и getDeclared...
В Reflection важно различать две группы методов. Например,
getMethods() возвращает публичные методы типа, включая подходящие унаследованные,
а getDeclaredMethods() — методы, объявленные непосредственно в данном классе или интерфейсе,
независимо от уровня доступа, но без унаследованных методов.
Та же идея есть у полей и конструкторов: выбор метода API зависит от того, ищем ли мы публично доступную поверхность типа или именно его собственное объявление.
class Account {
private long id;
public String owner() { return "Ann"; }
}
Field[] fields = Account.class.getDeclaredFields();
Method[] methods = Account.class.getDeclaredMethods();
Поиск конкретного члена
Когда известно имя и сигнатура, не обязательно перебирать массив. Можно запросить конкретный метод или конструктор и явно указать типы параметров.
Method method = String.class.getMethod("substring", int.class);
Constructor<StringBuilder> constructor =
StringBuilder.class.getConstructor(int.class);
Типы параметров являются частью сигнатуры запроса. Это особенно важно при перегрузке: одного имени метода недостаточно, чтобы однозначно выбрать нужный вариант.
getDeclaredField() или getDeclaredMethod()
могут найти непубличный член, но это ещё не означает, что код имеет право читать его или вызывать.