"La oss nå lage og bruke et par merknader."

"La oss for eksempel si at vi skriver en spillmotor. Spillet vårt har mange karakterer som faller inn i tre kategorier: alver, palassvakter og skurker."

"Når spillet utvikles, kan nye karakterer legges til, og dette vil endre spillbalansen. Derfor ville det være veldig praktisk å tildele hver "karakterklasse" sin egen merknad som beskriver dens fysiske egenskaper."

"Å gjøre det ville gjøre det veldig enkelt å simulere kamper mellom forskjellige karakterer og/eller raskt å beregne spillbalansen."

"Jeg er enig. Det er en god idé."

"La oss lage en @Person- kommentar som vil lagre liv, styrke og magi, samt angreps- og forsvarsparametere. Slik ser merknaden ut:"

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

"Og som et eksempel, her er hvordan beskrivelsen av en skogalvmage ville se ut:"

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

"Og her er hvordan beskrivelsen av hovedskurken ville se ut:"

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

"Jeg skjønner. Det minner meg litt om markørgrensesnitt."

"Ja. Bortsett fra at du for det første ikke trenger å arve noe. Og for det andre kan du lagre tilleggsinformasjon i merknader."

"Det er noen flere merknader som brukes til å merke merknader. Her er de: "

"@Retention-kommentaren indikerer hvor merknaden vår vil være synlig: bare i kildekoden, selv etter kompilering, eller til og med under kjøretid."

"@Target-kommentaren indikerer hva spesifikt kan merkes ved hjelp av merknaden: klasser, felt, metoder, metodeparametere, etc."

"Hvis vi vil at merknaden vår skal brukes på klasser som arver en kommentert klasse og ikke bare på selve den kommenterte klassen, så må vi annotere den med @Inherited."

"Slik vil @Person. -kommentaren vår se ut."

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

"Det var veldig interessant, takk, Rishi."

Men hvordan jobber du med disse merknadene i programmet? Hvordan bruker du dem? Hvordan leser du verdiene deres?"

"Dette gjøres vanligvis ved å bruke Reflection ."

"Slik vil vi finne ut hvilken karakter som er sterkest:"

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

"Her er metodene vi trenger:"

Metoder Beskrivelse
isAnnotationPresent(Annotation.class)
Sjekker om klassen har den angitte merknaden
getAnnotation(Annotation.class)
Returnerer et merknadsobjekt hvis klassen har den spesifiserte merknaden.
Annotation[] getAnnotations()
Returnerer en rekke av alle klassens merknader

"Flott. Jeg hadde ikke forventet at det ville være så enkelt å få en kommentar."

"Eh-he." Bare ring objektets getAnnotation-metode, og send inn ønsket merknadstype."

"Det var det for i dag."

"Takk, Rishi. Dette var en veldig interessant leksjon. Nå frykter jeg ikke kommentarer som jeg gjør vann."