"Agora vamos criar e usar algumas anotações."
"Por exemplo, digamos que estamos escrevendo um mecanismo de jogo. Nosso jogo tem muitos personagens que se enquadram em três categorias: elfos, guardas do palácio e vilões."
"Com o desenvolvimento do jogo, novos personagens podem ser adicionados, e isso vai alterar o equilíbrio do jogo. Assim, seria muito conveniente atribuir a cada 'classe de personagem' uma anotação própria que descreva suas características físicas."
"Fazer isso tornaria muito fácil simular batalhas entre diferentes personagens e/ou calcular rapidamente o equilíbrio do jogo."
"Eu concordo. É uma boa ideia."
"Vamos criar uma anotação @Person que armazenará vida, força e magia, bem como parâmetros de ataque e defesa. Veja como fica a anotação:"
@interface Person
{
String name() default "";
int live();
int strength();
int magic() default 0;
int attack() default 0;
int defense();
}
"E, como exemplo, aqui está a descrição de um mago elfo da floresta:"
@Person(live = 100, strength = 10, magic = 5, attack = 20, defense = 20)
class Elf
{
…
}
"E aqui está como ficaria a descrição do vilão principal:"
@Person(live = 1000, strength = 150, magic = 250, attack = 99, defense = 99)
class EvilMaster
{
…
}
"Entendo. Isso me lembra um pouco as interfaces de marcadores."
"Sim. Exceto, primeiro, você não precisa herdar nada. E segundo, você pode armazenar informações adicionais em anotações."
"Existem mais algumas anotações usadas para marcar anotações. Aqui estão elas: "
"A anotação @Retention indica onde nossa anotação ficará visível: somente no código-fonte, mesmo após a compilação, ou mesmo em tempo de execução."
"A anotação @Target indica o que especificamente pode ser marcado usando a anotação: classes, campos, métodos, parâmetros de método, etc."
"Se quisermos que nossa anotação seja aplicada a classes que herdam uma classe anotada e não apenas à própria classe anotada, precisamos anotá-la com @Inherited."
"É assim que nossa anotação @Person. ficaria."
@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();
}
"Isso foi muito interessante, obrigado, Rishi."
Mas como você trabalha com essas anotações no programa? Como você os usa? Como você lê seus valores?"
"Isso geralmente é feito usando o Reflection ."
"Aqui está como determinaríamos qual personagem é mais forte:"
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;
}
"Aqui estão os métodos que precisamos:"
Métodos | Descrição |
---|---|
|
Verifica se a classe tem a anotação especificada |
|
Retorna um objeto de anotação se a classe tiver a anotação especificada. |
|
Retorna um array de todas as anotações da classe |
"Ótimo. Eu não esperava que obter uma anotação fosse tão simples."
"Uh-huh." Basta chamar o método getAnnotation do objeto, passando o tipo de anotação desejado."
"Por hoje é isso."
"Obrigado, Rishi. Esta foi uma lição muito interessante. Agora não tenho medo de anotações como tenho medo de água."
GO TO FULL VERSION