„Acum să creăm și să folosim câteva adnotări.”

„De exemplu, să presupunem că scriem un motor de joc. Jocul nostru are o mulțime de personaje care se împart în trei categorii: spiriduși, paznici ai palatului și ticăloși.”

„Pe măsură ce jocul este dezvoltat, pot fi adăugate noi personaje, iar acest lucru va modifica echilibrul jocului. Astfel, ar fi foarte convenabil să îi atribui fiecărei „clase de caractere” propria sa adnotare care să-i descrie caracteristicile fizice.”

„Procedând astfel, ar fi foarte ușor să simulați bătălii între diferite personaje și/sau să calculați rapid echilibrul jocului.”

— Sunt de acord. E o idee bună.

„Să creăm o adnotare @Person care va stoca viața, puterea și magia, precum și parametrii de atac și apărare. Iată cum arată adnotarea:”

Exemplu
@interface Person
{
 String name() default "";
 int live();
 int strength();
 int magic() default 0;
 int attack() default 0;
 int defense();
}

„Și, ca exemplu, iată cum ar arăta descrierea unui mag elf de pădure:”

Exemplu
@Person(live = 100, strength = 10, magic = 5, attack = 20, defense = 20)
class Elf
{
 …
}

„Și iată cum ar arăta descrierea principalului răufăcător:”

Exemplu
@Person(live = 1000, strength = 150, magic = 250, attack = 99, defense = 99)
class EvilMaster
{
 …
}

— Înțeleg. Îmi amintește puțin de interfețele de marcare.

"Da. Cu excepția, în primul rând, că nu trebuie să moșteniți nimic. Și în al doilea rând, puteți stoca informații suplimentare în adnotări."

„Mai sunt câteva adnotări folosite pentru a marca adnotările. Iată-le:

„Adnotarea @Retention indică unde va fi vizibilă adnotarea noastră: numai în codul sursă, chiar și după compilare sau chiar în timpul execuției.”

„Adnotarea @Target indică ce anume poate fi marcat folosind adnotarea: clase, câmpuri, metode, parametri de metodă etc.”

„Dacă dorim ca adnotarea noastră să fie aplicată claselor care moștenesc o clasă adnotată și nu doar clasei adnotate în sine, atunci trebuie să o adnotăm cu @Inherited.”

„Așa ar arăta adnotarea noastră @Person. ”.

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

„A fost foarte interesant, mulțumesc, Rishi.”

Dar cum lucrezi cu aceste adnotări în program? Cum le folosești? Cum le citiți valorile?”

„Acest lucru se face, în general, folosind Reflection .”

„Iată cum am stabili care personaj este mai puternic:”

Exemplu
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;
}

„Iată metodele de care avem nevoie:”

Metode Descriere
isAnnotationPresent(Annotation.class)
Verifică dacă clasa are adnotarea specificată
getAnnotation(Annotation.class)
Returnează un obiect de adnotare dacă clasa are adnotarea specificată.
Annotation[] getAnnotations()
Returnează o matrice cu toate adnotările clasei

„Grozat. Nu mă așteptam să obțin o adnotare să fie atât de simplu.”

"Uh-huh." Pur și simplu apelați metoda getAnnotation a obiectului, trecând tipul de adnotare dorit."

— Asta e tot pentru azi.

"Mulțumesc, Rishi. Aceasta a fost o lecție foarte interesantă. Acum nu mă tem de adnotări cum fac apă."