Reflection — это механизм Java, позволяющий исследовать и изменять поведение классов, методов и полей во время выполнения. С аннотациями reflection используется для:
- чтения метаданных (например, какие методы помечены
@Transactional); - динамического вызова логики в зависимости от аннотаций (например, обработчики событий, DI-фреймворки);
- генерации кода или конфигурации на основе аннотаций.
В Java аннотации — это тоже объекты (интерфейсы), доступные через reflection API.
Класс Class, Method, Field, Constructor и Package имеют методы:
getAnnotation(Class<A> annotationClass)— возвращает аннотацию указанного типа илиnull;getAnnotations()— возвращает все аннотации (включая унаследованные);getDeclaredAnnotations()— возвращает только аннотации, объявленные явно (без наследования);isAnnotationPresent(Class<? extends Annotation> annotationClass)— проверяет наличие аннотации.
Создадим свою аннотацию и используем её на классе:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value();
}Применим:
public class Demo {
@MyAnnotation("test method")
public void doSomething() { }
}Прочитаем через reflection:
Class<?> clazz = Demo.class;
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
System.out.println("Метод " + method.getName() +
" помечен аннотацией со значением: " + ann.value());
}
}Вывод:
Метод doSomething помечен аннотацией со значением: test method
Чтобы работать с аннотацией через reflection, нужно указать:
@Retention(RetentionPolicy.RUNTIME)Иначе:
SOURCE— аннотация видна только компилятору (например,@Override);CLASS— сохраняется в class-файле, но недоступна во время выполнения;RUNTIME— доступна через reflection.
- Читают аннотации (
@Component,@Inject,@Autowired). - Создают объекты или прокси на основе метаданных.
- Аннотации вроде
@NotNull,@Sizeчитаются через reflection → валидатор проверяет входные данные.
@LogExecutionTime→ аспект ищет аннотированные методы и добавляет логи.
- Вы можете динамически вызвать метод или изменить его поведение, если на нём есть определённая аннотация.
- Reflection медленнее, чем прямой вызов, но для большинства задач это некритично (часто используется кеширование).
- Аннотации не могут иметь поведение — они только хранят данные (метаданные).
- Работа только с RUNTIME-аннотациями — аннотации с
CLASSиSOURCEобрабатываются либо компилятором, либо аннотационными процессорами (APT). - SecurityManager (в старых версиях Java) мог запрещать reflection, в современных — через модули (Java 9+).
- Reflection — работает во время выполнения (runtime).
- Annotation processing (
javax.annotation.processing) — работает во время компиляции, генерируя код или проверяя правильность использования аннотаций.
📌 Кратко для собеседования
Reflection позволяет во время выполнения получать аннотации у классов, методов и полей (
getAnnotation,isAnnotationPresent), а затем использовать эти метаданные для динамической конфигурации, DI, AOP или валидации. Чтобы аннотация была доступна через reflection, нужно указать@Retention(RetentionPolicy.RUNTIME).