Class, поля и методы

Базовый Java
≈ 2 мин чтения

Поля, методы и конструкторы тоже представлены объектами

Получив 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);

Типы параметров являются частью сигнатуры запроса. Это особенно важно при перегрузке: одного имени метода недостаточно, чтобы однозначно выбрать нужный вариант.

Получить описание private-члена и получить к нему доступ — разные вещи. getDeclaredField() или getDeclaredMethod() могут найти непубличный член, но это ещё не означает, что код имеет право читать его или вызывать.