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.