„Сега нека създадем и използваме няколко анотации.“

"Например, да кажем, че пишем двигател за игра. Нашата игра има много герои, които попадат в три категории: елфи, пазачи на двореца и злодеи."

„С развитието на играта може да се добавят нови герои и това ще промени баланса на играта. По този начин би било много удобно да присвоите на всеки „клас герои“ собствена анотация, която описва неговите физически характеристики.“

„Това би направило много лесно симулирането на битки между различни герои и/or бързото изчисляване на баланса на играта.“

— Съгласен съм. Това е добра идея.

„Нека създадем анотация @Person , която ще съхранява живот, сила и магия, Howто и параметри за атака и защита. Ето How изглежда анотацията:“

Пример
@interface Person
{
 String name() default "";
 int live();
 int strength();
 int magic() default 0;
 int attack() default 0;
 int defense();
}

„И като пример, ето How би изглеждало описанието на магьосник горски елф:“

Пример
@Person(live = 100, strength = 10, magic = 5, attack = 20, defense = 20)
class Elf
{}

„И ето How би изглеждало описанието на главния злодей:“

Пример
@Person(live = 1000, strength = 150, magic = 250, attack = 99, defense = 99)
class EvilMaster
{}

„Разбирам. Напомня ми малко за маркерни интерфейси.“

„Да. Освен че, първо, не е нужно да наследявате нищо. И второ, можете да съхранявате допълнителна информация в анотации.“

"Има още няколко анотации, използвани за маркиране на анотации. Ето ги: "

„Анотацията @Retention показва къде нашата анотация ще бъде видима: само в изходния code, дори след компилация or дори по време на изпълнение.“

„Анотацията @Target показва Howво конкретно може да бъде маркирано с помощта на анотацията: класове, полета, методи, параметри на метода и т.н.“

„Ако искаме нашата анотация да бъде приложена към класове, които наследяват анотиран клас, а не само към самия анотиран клас, тогава трябва да го анотираме с @Inherited.“

„Ето How би изглеждала нашата анотация @Person .“

Пример
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@interface Person
{
 String name() default "";
 int live();
 int strength();
 int magic() default 0;
 int attack() default 0;
 int defence();
}

„Беше много интересно, благодаря ти, Риши.“

Но How се работи с тези анотации в програмата? Как ги използвате? Как разчитате техните стойности?"

„Това обикновено се прави с помощта на Reflection .“

„Ето How ще определим кой характер е по-силен:“

Пример
public boolean fight(Class first, Class second)
{
 if (!first.isAnnotationPresent(Person.class))
  throw new RuntimeException("first param is not game person");
 if (!second.isAnnotationPresent(Person.class))
  throw new RuntimeException("second param is not game person");

 Person firstPerson = (Person) first.getAnnotation(Person.class);
 Person secondPerson = (Person) second.getAnnotation(Person.class);

 int firstAttack = firstPerson.attack() * firstPerson.strength() + firstPerson.magic();
 int firstPower = firstPerson.live() * firstPerson.defence() * firstAttack;

 int secondAttack = secondPerson.attack() * secondPerson.strength() + secondPerson.magic();
 int secondPower = secondPerson.live() * secondPerson.defence() * secondAttack;

 return firstPower > secondPower;
}

„Ето методите, от които се нуждаем:“

Методи Описание
isAnnotationPresent(Annotation.class)
Проверява дали класът има указаната анотация
getAnnotation(Annotation.class)
Връща обект с анотация, ако класът има указаната анотация.
Annotation[] getAnnotations()
Връща масив от всички анотации на класа

„Страхотно. Не очаквах, че получаването на анотация ще бъде толкова лесно.“

"Хм нали." Просто извикайте метода getAnnotation на обекта, като подадете желания тип анотация."

— Това е за днес.

„Благодаря ти, Риши. Това беше много интересен урок. Сега не се страхувам от анотации, Howто се страхувам от вода.“