Топ-100Аннотации в Java - CodOrbits
LogoCodOrbits

Раздел: Java Core

Раздел охватывает ключевые возможности языка Java: аннотации, исключения, generics, лямбда-выражения, интерфейсы и другие базовые концепции.

Все разделы
Иконка Java Core

Аннотации в Java

Last updated: 4 мая 2025 г.

Что такое аннотация в Java?

Представьте себе склад с коробками. На каждой из коробок есть надпись, которая говорит тому кто будет отгружать эти коробки из склада куда эту коробку отгружать.

Так вот, по этой аналогии коробка это класс или переменная или метод, а аннотация это эта надпись, а тот кто отгружает коробку и смотрит на надпись это компилятор Java, который смотрит на аннотацию и делает что-либо с классом или методом или переменной.

Например с помощью аннотации SafeVarargs над классом можно подавить некоторые предупреждения, которые компилятор бы выдал если бы над этим классом не было этой аннотации. То есть компилятор увидел над классом аннотацию SafeVarargs, которая говорит компилятору не выдавай предупреждения о классе и он этого делать не будет.

Или аннотация Documented скажет компилятору задокументировать класс над которым она стоит.

Далее на примерах разберем некоторые важные аннотации.


Аннотация Override

Override (должно быть самая часто встречающаяся аннотация). Этой аннотацией помечается метод для того чтобы всем программистам смотрящим на него было видно, что метод переопределяется (то есть в родительском классе класса в котором находиться этот метод помеченный аннотацией Override есть метод с таким же именем).

Поясним на примере:        

1import java.util.*;
2import java.lang.annotation.*;
3// Определим родительский класс
4class ParentClass {
5    // Этот метод будет переопределяться наследником.
6    public String someMethod() { return "parent method"; }
7}
8
9public class Annotations extends ParentClass {
10    // Аннотация Override сообщает программисту,
11    // который смотрит на метод ниже, что происходит
12    // переопределение метода родительского класса.
13    @Override
14    public String someMethod() {
15        return "overridden!";
16    }
17
18    public static void main(String[] args) {
19        Annotations test = new Annotations();
20        System.out.println(test.someMethod());
21    }
22}

Вывод:

Также еще служит как страховка.

То есть представим, что мы например случайно удалили или закомментировали метод в родительском классе, который переопределялся наследником. Если этот переопределяемый в наследнике метод был помечен аннотацией Override, то при запуске компилятор выдаст соответствующую ошибку сообщающую о том, что аннотация Override здесь ни к чему, поскольку в родительском методе нет метода с таким названием. В примере ниже в ParentClass мы не определили метода с именем someMethod (точнее метод закомментирован, как видим), поэтому программа выдаст ошибку.

1import java.util.*;
2import java.lang.annotation.*;
3
4// Определим родительский класс
5class ParentClass {
6    /*
7    public String someMethod() {return "parent method";}
8    */
9}
10
11public class Override1 extends ParentClass {
12
13    @Override // аннотация
14    public String someMethod() {return "overridden";}
15
16    public static void main(String[] args) {
17        Override1 test = new Override1();
18        test.someMethod();
19    }
20}

Вывод:


Аннотация @FunctionslInterface

FunctionalInterface – если над интерфейсом написать аннотацию @FunctionalInterface, то в такой интерфейс нельзя будет добавить более одного абстрактного метода (интерфейс с одним единственным абстрактным методом называется функциональным интерфейсом).

То есть если код содержит в себе интерфейс, который помечен аннотацией FunctionalInterface и который при этом содержит несколько абстрактных методов, то такой код не скомпилируется.

Search Icon

Что такое функциональный интерфейс, зачем он нужен и как им пользоваться разберем немного позже.

Поясним на примере:                                                

1// Deprecated и FunctionalInterface
2import java.util.*;
3import java.lang.annotation.*;
4
5@FunctionalInterface
6interface Print {
7    // Здесь в функциональном интерфейсе должен быть
8    // один абстрактный метод, а их как видим два.
9    void printString(String testString);
10    void printAnotherString(String testString);
11}
12
13public class AnotherAnnotations {
14    public static void main(String[] args) {
15        AnotherAnnotations swDemo = new AnotherAnnotations();
16    }
17}

Вывод:

Как видим код не скомпилировался.                      


Аннотация @Deprecated

Deprecatedдля пометки устаревших методов или классов.

При вызове метода вызовется предупреждение, что метод устарел и что его лучше не использовать.

Поясним на примере:

1import java.util.*;
2import java.lang.annotation.*;
3
4class ParentClass {
5    public String getName() { return "mike"; }
6
7    // метод ниже устарел
8    @Deprecated
9    public void deprecatedMethod() {
10        System.out.println("This is a legacy function");
11    }
12}
13
14public class AnotherAnnotations extends ParentClass {
15    public static void main(String[] args) {
16        AnotherAnnotations swDemo = new AnotherAnnotations();
17        swDemo.deprecatedMethod();
18    }
19}

Вывод:

Как видим, код скомпилировался, но при компиляции было вызвано предупреждение.      


Создание собственных (кастомных) аннотаций.

Можно создавать свои аннотации с помощью аннотации @interface.

При создании аннотации используются вспомогательные аннотации. Они пишутся над аннотацией @interface.

@Target – этой аннотацией указываем к чему будет применяться создаваемая аннотация – если укажем TYPE, то только к классу, если METHOD, то только к методу, если FIELD, то только к полю, есть и другие значения, но это основные

@Retention – этой аннотацией указываем где будет жить создаваемая аннотация – если укажем RUNTIME, то создаваемая аннотация должна быть доступна джава машине во время выполнения, если CLASS, то аннотация не будет доступна во время выполнения, но будет в скомпилированном джава class файле, если SOURCE, то создаваемая аннотация будет содержаться только в исходном коде.

@Repeatable(...) – создаваемая аннотация может использоваться несколько раз на методе, классе или поле. В скобочках указывается другая кастомная аннотация. Эта другая кастомная аннотация будет хранить в виде массива ВСЕ повторения применения над конкретным методом или классом, или полем той кастомной аннотации над которой мы писали Repeatable.

@Inherited – создаваемая аннотация наследуется классами, которые наследуют класс к которому применена аннотация.

@Documented – информация о создаваемой аннотации появиться в JavaDoc-документации  

Поясним на примере:  

1import java.util.*;
2import java.lang.annotation.*;
3
4//Создадим аннотацию с именем RepeatableCompany
5//Для начала к создаваемой аннотации RepeatableCompany
6//применим необходимые вспомогательные аннотации.
7
8//Применим @Inherited. Значит, что к наследникам
9//классов к которым будет применена создаваемая
10//аннотация тоже будет применена эта аннотация.
11//То есть можно увидеть, что аннотация
12//RepeatableCompany применена к классу CompanyClass,
13//а значит и к классу CreateAnnotation она тоже будет
14//применена так как CreateAnnotation это наследник
15//класса CompanyClass.
16@Inherited
17
18//Применим @Documented.
19//Значит создаваемая аннотация будет задокументирована
20@Documented
21
22//Применим @Target(ElementType.TYPE).
23//Значит создаваемая аннотация будет использоваться
24//над классами
25@Target(ElementType.TYPE)
26
27//Применим @Repeatable(RepeatableCompanies.class).
28//Значит создаваемую аннотацию можно будет применять
29//несколько раз на один и тот же класс.
30//RepeatableCompanies – это аннотация, которая
31//содержит массив из всех аннотаций RepeatableCompany,
32//примененных к классу и к какому нибудь
33//классу храниться в RepeatableCompanies.
34@Repeatable(RepeatableCompanies.class)
35
36//Применим @Retention(RetentionPolicy.RUNTIME). Значит
37//создаваемая аннотация доступна при работе программы.
38@Retention(RetentionPolicy.RUNTIME)
39
40//Теперь приступим непосредственно
41//к созданию @RepeatableCompany.
42@interface RepeatableCompany {
43    //При создании аннотации в ней можно определять
44    //поля аннотации. Ниже можно увидеть пример
45    //пары полей. В аннотации они определяются чтобы
46    //при применении аннотации над каким-то классом,
47    //можно было записываться в такие
48    //поля какие-то данные которые будут
49    //доступны при выполнении над объектом класса
50    //к которому была применена аннотация.
51    //Ниже можно увидеть пример аннотации которая
52    //будет создана просто и не будет выполнять
53    //никаких действий над классом к которому она
54    //будет применяться, поля аннотации будут
55    //содержать какие-то данные которые можно будет
56    //использовать при выполнении программы.
57    //Пример ниже показывает как аннотация смотрит
58    //внутри и как она будет применяться.
59    //Например:
60    @RepeatableCompany(name="Toyota Motor",city="Tokyo")
61    //аннотация будет видна в коде класса
62    //CompanyClass в котором она указана.
63    String name() default "CompanyName";
64    String city() default "CompanyCity";
65    //default это дефолтное значение поля.
66    //То есть программист может не указывать
67    //name = "Toyota Motor", city = "Tokyo" в скобочках
68    //у аннотации, а просто применить над классом
69    //аннотацию без ничего вот так: @RepeatableCompany.
70    //И так как в скобочках ничего не было указано
71    //то name и city будут содержать дефолтные
72    //значения – "CompanyName" и "CompanyCity".
73}
74
75@Documented
76@Inherited
77@Target(ElementType.TYPE)
78@Retention(RetentionPolicy.RUNTIME)
79@interface RepeatableCompanies {
80    //массив аннотаций RepeatableCompany
81    RepeatableCompany[] value() default{};
82}
83
84@RepeatableCompany
85@RepeatableCompany(name = "Toyota Motor",city = "Tokyo")
86@RepeatableCompany(name = "Woltzvagen",city = "Germany")
87class CompanyClass {
88    public String getName() {return "mike";}
89}
90
91class CreateAnnotation extends CompanyClass {
92    public static void main(String[] args) {
93        //Созданная аннотация чисто для информации
94        //программисту, поэтому в мейн ничего не делаем.
95    }
96}

Дополнительные материалы

Официальный гайд по аннотациям от Oracle

Additional Material Icon
Divider

Статья о создании кастомных аннотаций

Additional Material Icon
Divider

Создание кастомных аннотаций (JournalDev)

Additional Material Icon

Следующие уроки

Обработка исключений

10
мин.

Similar Articles Icon
Divider

Generics в Java

9
мин.

Similar Articles Icon
Divider

Приведение типов

8
мин.

Similar Articles Icon