Reflection в Java

Reflection позволяет во время выполнения исследовать типы и обращаться к конструкторам, полям и методам. Базовые API находятся в java.lang.Class и java.lang.reflect.

Class<?> type = Class.forName("example.Command");
Constructor<?> constructor = type.getDeclaredConstructor(String.class);
Object command = constructor.newInstance("run");
 
Method method = type.getMethod("execute");
Object result = method.invoke(command);

Вызов оборачивает исключение целевого метода в InvocationTargetException; исходная причина лежит в getCause().

Где используется

  • dependency injection и component scanning;
  • сериализация/маппинг;
  • ORM;
  • тестовые инструменты;
  • plugin-механизмы.

Обычно фреймворк сканирует метаданные один раз, строит план доступа и кэширует его. Для производительных низкоуровневых вызовов существуют method handles и генерация кода.

Доступ и модули

getDeclaredXxx видит непубличное объявление, но это ещё не разрешение доступа. setAccessible(true) может быть запрещён strong encapsulation модулей. Открывать package через параметры JVM ради случайного обхода — признак хрупкой интеграции.

Generic-типы частично доступны из деклараций как ParameterizedType, но объект List<String> в runtime не хранит отдельный класс от List<Integer> из-за type erasure.

Риски

  • ошибки имени и типа переносятся из compile time в runtime;
  • сложнее навигация и рефакторинг;
  • доступ может сломаться после обновления модуля/JDK;
  • reflection в горячем цикле требует измерения;
  • нельзя считать обход private стабильным API.

На собеседовании

Чем getDeclaredMethod отличается от getMethod? Первый ищет объявленный метод любой видимости, второй — публичный с учётом наследования.

Почему method.invoke бросает InvocationTargetException? Он отделяет ошибку механизма вызова от исключения целевого метода.

Сохраняется ли List<String> как отдельный runtime-класс? Нет.

Гарантирует ли setAccessible(true) доступ? Нет, модули и runtime-политика могут запретить.

Связано: Класс Class, Аннотации, Class loader.