Динамический доступ через Reflection
Когда член выбирается во время выполнения
Reflection умеет не только описывать структуру типа. Объекты Field,
Method и Constructor могут использоваться для динамического доступа.
Это нужно, например, инфраструктурному коду, который получает имя метода из конфигурации
или создаёт экземпляр класса, выбранного только во время запуска.
Вызов метода через Method
class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}
Greeter greeter = new Greeter();
Method method = Greeter.class.getMethod("greet", String.class);
Object result = method.invoke(greeter, "Ann");
Первый аргумент invoke() — объект, на котором вызывается экземплярный метод,
а остальные значения передаются как его аргументы. Возвращаемое значение имеет тип Object,
потому что Reflection заранее не знает конкретный тип результата в месте вызова.
Создание объекта через Constructor
Constructor<StringBuilder> constructor =
StringBuilder.class.getConstructor(int.class);
StringBuilder builder = constructor.newInstance(64);
Вместо прямого new сначала выбирается описание конструктора,
а затем newInstance() создаёт объект с переданными аргументами.
Чтение и изменение поля
class Counter {
public int value = 10;
}
Counter counter = new Counter();
Field field = Counter.class.getField("value");
int oldValue = (int) field.get(counter);
field.set(counter, 20);
У статического поля объект-получатель не нужен, а для поля экземпляра нужно передать конкретный объект. Reflection проверяет совместимость типов во время выполнения, поэтому многие ошибки, которые при прямом обращении поймал бы компилятор, здесь проявляются позже.
Непубличные члены и доступность
Для непубличного члена одного getDeclared... недостаточно.
Reflection всё равно учитывает правила доступа. trySetAccessible()
может попытаться разрешить доступ и вернуть false, если это невозможно.
В модульном приложении границы модулей и открытых пакетов также ограничивают такой доступ.