Основы рефлексии

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

Class — описание типа во время выполнения

Обычно Java-код работает с объектами и вызывает известные заранее методы. Reflection нужен, когда программе требуется исследовать сам тип во время выполнения: узнать его имя, родительский класс, интерфейсы, аннотации или доступные члены. Точкой входа служит объект Class<?>.

Class<String> type = String.class;

System.out.println(type.getName());
System.out.println(type.getSimpleName());

Объект Class не является экземпляром String. Он представляет описание самого типа String в работающей JVM.

Как получить Class

Когда тип известен в коде, проще всего использовать литерал .class. Если уже есть объект, его тип можно получить через getClass().

String text = "hello";

Class<String> first = String.class;
Class<? extends String> second = text.getClass();

Когда имя класса приходит как строка во время выполнения, существует Class.forName(). Такой вариант встречается в инфраструктурном коде, где конкретный тип заранее неизвестен исходному коду.

Class<?> type = Class.forName("java.util.ArrayList");
System.out.println(type.getSimpleName());

Что можно узнать о типе

Через Class можно проверить, представляет ли объект интерфейс, enum, record или массив, получить пакет, суперкласс и реализованные интерфейсы, а также перейти к полям, методам, конструкторам и аннотациям. Эти группы мы разберём отдельно, чтобы не превращать Reflection в список методов API.

Reflection нужен не для обычных вызовов. Если конкретный тип и метод известны при компиляции, прямой вызов обычно проще, понятнее и безопаснее. Reflection полезен именно тогда, когда структура выбирается или исследуется динамически.