JavaRush /Курсы /Модуль 2. Java Core /Обработка аннотаций в рантайме

Обработка аннотаций в рантайме

Модуль 2. Java Core
18 уровень , 4 лекция
Открыта

Создание аннотаций — процесс довольно простой, хоть и ограниченый некоторыми правилами. Теперь нам нужно разобраться, в чем их польза на практике.

Давай вспомним, как мы создаем свою аннотацию.

Пишем аннотацию, которая будет аннотировать классы и методы и содержать информацию об авторе и версии:


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
   String author() default "Author";
   String version() default "0.0";
}

Наши классы, к которым мы добавили аннотацию:


@Info
public class MyClass1 {
   @Info
   public void myClassMethod() {}
}
 
@Info(version = "2.0")
public class MyClass2 {
   @Info(author = "Anonymous")
   public void myClassMethod() {}
}
 
@Info(author = "Anonymous", version = "2.0")
public class MyClass3 {
   @Info(author = "Anonymous", version = "4.0")
   public void myClassMethod() {}
}

Как же нам воспользоваться этими данными на этапе работы программы?

Извлечь метаданные из аннотаций можно с помощью рефлексии. Вспомним, что такое рефлексия. Это механизм исследования данных о программе во время ее выполнения. Рефлексия позволяет получать информацию о полях, методах, конструкторах классов, а также о классах.

С помощью рефлексии мы прочитаем аннотации в классе и выведем необходимую нами информацию.

Распознаем данные из наших классов в main:


import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
 
public class Main {
   public static void main(String[] args) throws NoSuchMethodException {
       readMyClass(MyClass1.class);
       readMyClass(MyClass2.class);
       readMyClass(MyClass3.class);
   }
 
   static void readMyClass(Class<?> myClassObj) throws NoSuchMethodException {
       System.out.println("\nКласс " + myClassObj.getName());
       readAnnotation(myClassObj);
       Method method = myClassObj.getMethod("myClassMethod");
       readAnnotation(method);
   }
 
   static void readAnnotation(AnnotatedElement element) {
       try {
           System.out.println("Поиск аннотаций в " + element.getClass().getName());
           Annotation[] annotations = element.getAnnotations();
           for (Annotation annotation : annotations) {
               if (annotation instanceof Info) {
                   final Info fileInfo = (Info) annotation;
                   System.out.println("Автор: " + fileInfo.author());
                   System.out.println("Версия: " + fileInfo.version());
               }
           }
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

В метод readMyClass мы передаем экземпляр нашего класса на обработку.

Далее в метод readAnnotation мы можем передать как класс, так и метод. Так и поступим: передаем туда объект класса и объект метода. Принимается объект, который реализует контракт AnnotatedElement. Это позволяет достать из него список аннотаций и прочитать информацию по каждой из них.

Обрати внимание на то, что мы не достанем информацию, не проверив принадлежность аннотации к нашему типу аннотации (if (annotation instanceof Info)).

На выходе мы получаем полную информацию из аннотаций:

Класс annotation.MyClass1
Поиск аннотаций в java.lang.Class
Автор: Author
Версия: 0.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Author
Версия: 0.0

Класс annotation.MyClass2
Поиск аннотаций в java.lang.Class
Автор: Author
Версия: 2.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Anonymous
Версия: 0.0

Класс annotation.MyClass3
Поиск аннотаций в java.lang.Class
Автор: Anonymous
Версия: 2.0
Поиск аннотаций в java.lang.reflect.Method
Автор: Anonymous
Версия: 4.0

Так с помощью рефлексии мы смогли извлечь метаинформацию.

Теперь рассмотрим пример использования аннотаций для усовершенствования кода, в том числе повышения читаемости, скорости роботы и качества в целом. В этом нам поможет Lombok.

Lombok — это плагин-надстройка компилятора, который с помощью ключевых слов-аннотаций скрывает огромное количество кода, расширяя язык и тем самым упрощая разработку и добавляя некоторую функциональность.

Рассмотрим пример аннотаций из Lombok:

@ToString Генерирует реализацию для метода toString(), которая состоит из аккуратного представления объекта: имя класса, все поля и их значения.

@ToString
public class Example
@EqualsAndHashCode Генерирует реализации equals и hashCode, которые по умолчанию используют нестатические и нестационарные поля, но настраиваются. Подробнее можно прочитать на сайте проекта. Там описан пример с использованием @EqualsAndHashCode и без него со стандартной реализацией.
@Getter / @Setter Генерирует геттеры и сеттеры для частных полей.

@Getter 
@Setter 
private String name = “name”;
@NonNull Используются для утверждения, что поля не являются null при создании экземпляра объекта. Иначе выбрасывается исключение NullPointerException.

public Example(@NonNull P p) {
 super("Hello");
 this.name = p.getName();
}

У Lombok есть еще много полезных аннотаций, которые используются реже. Мы рассмотрели простую часть его аннотаций. Про сам проект можно почитать больше на официальном сайте.

Комментарии (4)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Alexander Уровень 46
26 октября 2025
На последней задаче настроился уже на долгую битву, а оказалось название задачи сильно страшнее, чем ее решение)
Ardan Уровень 57
4 июля 2025
последняя задача предвещала быть сложной в иоге решилась по щелчку пальца
Rick_Sanchez Уровень 41
10 мая 2022
что это за закрытые лекции и где их найти и как открыть? почему их нет в основной ветке квестов?
Зепп Бранниган Уровень 7 Moderator
11 мая 2022
Это лекция из нашего курса Java-университет.