A criação de anotações é um processo bastante simples, embora seja limitado por algumas regras. Agora precisamos descobrir a que propósito prático eles servem.
Vamos relembrar como criamos nossa própria anotação.
Escreveremos uma anotação que é para classes e métodos e contém informações sobre o autor e a versão do código:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
String author() default "Author";
String version() default "0.0";
}
Aqui estão nossas classes que anotamos:
@Info
public class MyClass1 {
@Info
public void myClassMethod() {}
}
@Info(version = "2.0")
public class MyClass2 {
@Info(author = "Anonymous")
public void myClassMethod() {}
}
@Info(author = "Anonymous", version = "2.0")
public class MyClass3 {
@Info(author = "Anonymous", version = "4.0")
public void myClassMethod() {}
}
Como podemos usar esses dados em tempo de execução?
Usando reflexão para extrair metadados de anotações. Lembre-se do que é reflexão. A reflexão é um mecanismo para examinar dados sobre um programa em tempo de execução. A reflexão permite obter informações sobre campos, métodos, construtores de classe e classes.
Usaremos a reflexão para ler as anotações em uma classe e exibir as informações que desejamos.
Leremos os dados de nossas classes no método main :
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
readMyClass(MyClass1.class);
readMyClass(MyClass2.class);
readMyClass(MyClass3.class);
}
static void readMyClass(Class<?> myClassObj) throws NoSuchMethodException {
System.out.println("\nClass: " + myClassObj.getName());
readAnnotation(myClassObj);
Method method = myClassObj.getMethod("myClassMethod");
readAnnotation(method);
}
static void readAnnotation(AnnotatedElement element) {
try {
System.out.println("Search for annotations in " + element.getClass().getName());
Annotation[] annotations = element.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof Info) {
final Info fileInfo = (Info) annotation;
System.out.println("Author: " + fileInfo.author());
System.out.println("Version: " + fileInfo.version());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Passamos uma instância de nossa classe para o método readMyClass .
Então podemos passar uma classe, bem como um método para o método readAnnotation . Vamos fazer isso — passaremos um objeto Class e um objeto Method. É necessário um objeto que implemente a interface AnnotatedElement . Isso nos permite obter uma lista de anotações do objeto e obter informações sobre cada uma delas.
Observe que só obtemos informações depois de verificar se a anotação pertence ao nosso tipo de anotação: if (annotation instanceof Info) .
A saída do programa nos dá informações completas das anotações:
Pesquisar anotações em java.lang.Class
Autor: Autor
Versão: 0.0
Pesquisar anotações em java.lang.reflect.Method
Autor: Autor
Versão: 0.0
Classe: annotation.MyClass2
Pesquisar anotações em java.lang.
Autor da classe : Autor
Versão: 2.0
Pesquisar anotações em java.lang.reflect.Method
Autor: Anônimo
Versão: 0.0
Classe: annotation.MyClass3
Pesquisar anotações em java.lang.Class
Autor: Anônimo
Versão: 2.0
Pesquisar anotações em java. lang.reflect.Method
Autor: Anônimo
Versão: 4.0
Assim, com a ajuda da reflexão, conseguimos extrair os metadados.
Agora vamos ver um exemplo de uso de anotações para melhorar o código, incluindo o aumento da legibilidade, velocidade e qualidade em geral. Lombok nos ajudará com isso.
Lombok é um plug-in de compilador que usa anotações para ocultar uma grande quantidade de código e estender a linguagem, simplificando o desenvolvimento e adicionando algumas funcionalidades.
Considere um exemplo de anotações do Lombok:
@Para sequenciar | Gera uma implementação do método toString() que consiste em uma representação completa do objeto: o nome da classe, todos os campos e seus valores. |
|
@EqualsAndHashCode | Gera implementações de equals e hashCode que usam campos não estáticos e não estáticos por padrão, mas são configuráveis. | Mais detalhes podem ser encontrados no site do projeto . Lá você encontrará um exemplo que usa @EqualsAndHashCode e também mostra uma implementação padrão sem a anotação. |
@Getter / @Setter | Gera getters e setters para campos privados. |
|
@NonNull | Usado para afirmar que os campos não são nulos quando um objeto é instanciado. Caso contrário, um NullPointerException é lançado. |
|
O Lombok tem muitas anotações mais úteis que são usadas com menos frequência. Consideramos suas anotações mais simples. Você pode ler mais sobre o projeto no site oficial .