"Now let's create and use a couple of annotations."

"For example, let's say we're writing a game engine. Our game has a lot of characters that fall into three categories: elves, palace guards, and villains."

"As the game is developed, new characters may be added, and this will alter the game balance. Thus, it would be very convenient to assign each 'character class' its own annotation that describes its physical characteristics."

"Doing so would make it very easy to simulate battles between different characters and/or quickly calculating the game balance."

"I agree. That's a good idea."

"Let's create a @Person annotation that will store life, strength, and magic, as well as attack and defense parameters. Here's how the annotation looks:"

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

"And, as an example, here's what the description of a forest elf mage would look like:"

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

"And here's how the description of the main villain would look:"

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

"I see. It reminds me a little of marker interfaces."

"Yes. Except, first, you don't have to inherit anything. And second, you can store additional information in annotations."

"There are a few more annotations used to mark annotations. Here they are:"

"The @Retention annotation indicates where our annotation will be visible: only in the source code, even after compilation, or even at run time."

"The @Target annotation indicates what specifically can be marked using the annotation: classes, fields, methods, method parameters, etc."

"If we want our annotation to be applied to classes that inherit an annotated class and not just to the annotated class itself, then we need to annotate it with @Inherited."

"This is what our @Person. annotation would look like."

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

"That was very interesting, thank you, Rishi."

But how do you work with these annotations in the program? How do you use them? How do you read their values?"

"This is generally done using Reflection."

"Here's how we would determine which character is stronger:"

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

"Here are the methods that we need:"

Methods Description
isAnnotationPresent(Annotation.class)
Checks whether the class has the specified annotation
getAnnotation(Annotation.class)
Returns an annotation object if the class has the specified annotation.
Annotation[] getAnnotations()
Returns an array of all of the class's annotations

"Great. I didn't expect getting an annotation would be so simple."

"Uh-huh." Simply call the object's getAnnotation method, passing in the desired annotation type."

"That's it for today."

"Thank you, Rishi. This was a very interesting lesson. Now I don't fear annotations like I do water."