Что позволит аннотации быть доступной при выполнении программы
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
@Retention: Сделать аннотации доступными при выполнении программы
Это ключевой вопрос о метаанотации @Retention, которая определяет, как долго аннотация остаётся доступной для программы. По умолчанию большинство аннотаций удаляются после компиляции, что делает их недоступными во время выполнения (runtime).
Проблема: Аннотации исчезают после компиляции
По умолчанию Java удаляет информацию об аннотациях после компиляции:
// Эта аннотация НЕ будет доступна во время выполнения
@interface MyAnnotation {
String value();
}
// При компиляции информация об аннотации теряется!
@MyAnnotation("Important")
public void doSomething() {
// ...
}
Решение: @Retention(RetentionPolicy.RUNTIME)
Чтобы сделать аннотацию доступной при выполнении программы, нужно добавить метаанотацию @Retention с политикой RUNTIME:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME) // ОБЯЗАТЕЛЬНО!
public @interface MyAnnotation {
String value();
int priority() default 0;
}
Три политики @Retention
1. RetentionPolicy.SOURCE (удаляется при компиляции)
@Retention(RetentionPolicy.SOURCE)
public @interface Deprecated {
String value();
}
Характеристики:
- Аннотация доступна только исходном коде
- Удаляется при компиляции в .class файл
- Недоступна во время выполнения (runtime)
- Используется только для компилятора и IDE
Пример: @Override, @SuppressWarnings
2. RetentionPolicy.CLASS (в .class файле, но не во время выполнения)
@Retention(RetentionPolicy.CLASS) // По умолчанию
public @interface MyClassLevelAnnotation {
}
Характеристики:
- Сохраняется в скомпилированном .class файле
- НЕ доступна при выполнении программы (runtime)
- Доступна инструментам для анализа bytecode
- Это значение по умолчанию
3. RetentionPolicy.RUNTIME (доступна при выполнении)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeAnnotation {
String name() default "";
int version() default 1;
}
Характеристики:
- Сохраняется в .class файле
- Доступна при выполнении программы (runtime)
- Можно получить через Reflection
- Используется фреймворками (Spring, Hibernate, Jackson)
Практический пример: Валидация полей
// Определение аннотации для валидации
@Retention(RetentionPolicy.RUNTIME) // ВАЖНО!
@Target(ElementType.FIELD)
public @interface Validate {
String pattern() default ".*";
int minLength() default 0;
int maxLength() default Integer.MAX_VALUE;
}
// Класс с аннотированными полями
public class User {
@Validate(minLength = 3, maxLength = 20)
private String username;
@Validate(pattern = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+")
private String email;
}
// Валидатор, использующий Reflection
public class AnnotationValidator {
public static void validate(Object obj) throws IllegalAccessException {
Class clazz = obj.getClass();
for (Field field : clazz.getDeclaredFields()) {
Validate validation = field.getAnnotation(Validate.class);
if (validation != null) {
field.setAccessible(true);
String value = (String) field.get(obj);
// Проверка длины
if (value.length() < validation.minLength()) {
throw new IllegalArgumentException(
field.getName() + " is too short"
);
}
if (value.length() > validation.maxLength()) {
throw new IllegalArgumentException(
field.getName() + " is too long"
);
}
}
}
}
}
Примеры @Retention в популярных фреймворках
// Spring Framework
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Transactional {
String value() default "";
}
// Hibernate
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String name() default "";
}
// Jackson
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonProperty {
String value();
}
Сравнение политик
| Политика | Доступна в исходном коде | В .class файле | При выполнении |
|---|---|---|---|
| SOURCE | Да | Нет | Нет |
| CLASS | Да | Да | Нет |
| RUNTIME | Да | Да | Да (Reflection) |
Типичный ответ на собеседовании
Чтобы аннотация была доступна при выполнении программы, нужно использовать @Retention(RetentionPolicy.RUNTIME).
По умолчанию информация об аннотациях удаляется после компиляции. Но если добавить эту метаанотацию, информация сохраняется в .class файле и доступна через Reflection.
Без RUNTIME политики, даже если аннотация определена, её информация будет недоступна при выполнении.
Вывод: @Retention(RetentionPolicy.RUNTIME) делает аннотацию доступной для Reflection во время выполнения программы.