Основното предимство на анотациите не идва от използването на стандартните, които вече са в JDK. В същото време рядко има нужда да създадете своя собствена анотация. Но ако разработваме голяма система or създаваме отделна библиотека, тогава на архитектурно ниво внедряването на нашата собствена анотация определено ще донесе дивиденти.

Нека се опитаме да създадем анотация.

За да направите това, създайте файл, но instead of да пишете class or интерфейс , напишете @interface . Това ще бъде файлът за нашата анотация. Вътрешната структура на анотацията е подобна на тази на интерфейса.

public @interface Sum {
   int sum() default 0;
}

@interface показва, че това е анотация,
default казва, че параметърът ще има конкретна стойност по подразбиране.

Та-да! Създадохме анотация! Теоретично вече можем да го използваме, но първо би било по-добре да го конфигурираме.

Без конфигурация нашата анотация може да се приложи към всичко (към класове, методи, атрибути и т.н.), така че няма смисъл да се използва на този етап. Колкото и странно да изглежда, нашата анотация трябва да бъде анотирана с други анотации!

Да започнем с @Target .

Анотацията @Target (уместна от Java 1.5) ограничава възможността за прилагане на анотация. За да ограничим използването до определено ниво, трябва да предадем аргумент към анотацията @Target , за да посочим към кои типове може да се приложи. Ето някои от често използваните типове:

@Target(ElementType.PACKAGE) за пакети
@Target(ElementType.TYPE) за класове
@Target(ElementType.CONSTRUCTOR) за конструктори
@Target(ElementType.METHOD) за методи
@Target(ElementType.FIELD) за атрибути (променливи) в клас
@Target(ElementType.PARAMATER) за параметрите на метода
@Target(ElementType.LOCAL_VARIABLE) за локални променливи

Ако имате нужда от анотация за няколко типа, тогава можете да предадете няколко аргумента като масив:

@Target({ ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

Следващата важна част от конфигурацията е анотацията @Retention .

Тази анотация показва частите от жизнения цикъл на codeа, в които нашата анотация ще бъде достъпна:

RetentionPolicy.SOURCE Анотациите, маркирани с политиката за задържане SOURCE , се отхвърлят по време на изпълнение.
RetentionPolicy.CLASS Анотациите, маркирани с политиката за запазване на CLASS , се записват във file .class , но се премахват по време на изпълнение.
RetentionPolicy.RUNTIME Анотациите, маркирани с политиката за задържане RUNTIME , продължават да съществуват по време на изпълнение и могат да бъдат достъпни в нашата програма по време на изпълнение.

Има още няколко пояснения, които можете да използвате за конфигуриране:

Анотация Стойност
@Наследено Показва, че производен клас наследява изпълнението на анотацията от родителския клас.
@Документирано Това показва, че анотацията ще бъде включена в генерираната Javadoc documentация.

Сега нека се опитаме да създадем наша собствена анотация.

Ще създадем анотация, която е за класове и методи и съдържа информация за автора и versionта на codeа:

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

Можем да приложим нашата анотация към методи и класове. Метаданните на нашата анотация ще бъдат достъпни по време на изпълнение. Обърнете внимание на параметрите на нашата анотация: можем да предоставим два аргумента (автор и version) or можем да ги пропуснем. Ако ги пропуснем, ще се използват зададените стойности по подразбиране ( по подразбиране „Author“ и по подразбиране „0.0“ ).

Струва си да се отбележи, че не е необходимо да указваме стойност по подразбиране за параметрите. В този случай параметърът става задължителен.

Когато предаваме аргументи, трябва да посочим съответния параметър, използвайки нотацията value = "value" . Параметърът винаги трябва да бъде назован изрично, дори ако анотацията има един параметър.

Нека приложим нашата анотация към няколко класа:

@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() {}
}