← Назад к вопросам

Что позволит аннотации быть доступной при выполнении программы

2.0 Middle🔥 121 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

@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 во время выполнения программы.