La creazione di annotazioni è un processo abbastanza semplice, sebbene sia limitato da alcune regole. Ora dobbiamo capire a quale scopo pratico servono.

Ricordiamo come creiamo la nostra annotazione.

Scriveremo un'annotazione per classi e metodi e conterrà informazioni sull'autore e la versione del codice:


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
   String author() default "Author";
   String version() default "0.0";
}

Ecco le nostre classi che abbiamo annotato:


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

Come possiamo utilizzare questi dati in fase di esecuzione?

Utilizzando la riflessione per estrarre i metadati dalle annotazioni. Ricorda cos'è la riflessione. La riflessione è un meccanismo per esaminare i dati su un programma in fase di esecuzione. Reflection consente di ottenere informazioni su campi, metodi, costruttori di classi e classi.

Useremo la riflessione per leggere le annotazioni in una classe e visualizzare le informazioni che vogliamo.

Leggeremo i dati dalle nostre classi nel metodo principale :


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

Passiamo un'istanza della nostra classe al metodo readMyClass .

Quindi possiamo passare una classe e un metodo al metodo readAnnotation . Facciamolo: passeremo un oggetto Class e un oggetto Method. Prende un oggetto che implementa l' interfaccia AnnotatedElement . Questo ci consente di ottenere un elenco di annotazioni dall'oggetto e ottenere informazioni su ciascuna di esse.

Si noti che otteniamo informazioni solo dopo aver verificato se l'annotazione appartiene al nostro tipo di annotazione: if (annotation instanceof Info) .

L'output del programma ci fornisce informazioni complete dalle annotazioni:

Classe: annotation.MyClass1
Cerca annotazioni in java.lang.Class
Autore: Author
Versione: 0.0
Cerca annotazioni in java.lang.reflect.Method
Autore: Author
Versione: 0.0

Classe: annotation.MyClass2
Cerca annotazioni in java.lang. Classe
Autore: Autore
Versione: 2.0
Cerca annotazioni in java.lang.reflect.Method
Autore: Anonimo
Versione: 0.0

Classe: annotation.MyClass3
Cerca annotazioni in java.lang.Class
Autore: Anonimo
Versione: 2.0
Cerca annotazioni in java. lang.reflect.Method
Autore: Anonimo
Versione: 4.0

Così, con l'aiuto della riflessione, siamo stati in grado di estrarre i metadati.

Ora diamo un'occhiata a un esempio di utilizzo delle annotazioni per migliorare il codice, incluso l'aumento della leggibilità, della velocità e della qualità in generale. Lombok ci aiuterà in questo.

Lombok è un plug-in del compilatore che utilizza le annotazioni per nascondere un'enorme quantità di codice ed estendere il linguaggio, semplificando così lo sviluppo e aggiungendo alcune funzionalità.

Considera un esempio di annotazioni da Lombok:

@Accordare Genera un'implementazione del metodo toString() che consiste in una rappresentazione completa dell'oggetto: il nome della classe, tutti i campi e i relativi valori.

@ToString
public class Example
@EqualsAndHashCode Genera implementazioni di equals e hashCode che utilizzano campi non statici e non statici per impostazione predefinita, ma sono configurabili. Maggiori dettagli possono essere trovati sul sito web del progetto . Lì troverai un esempio che utilizza @EqualsAndHashCode e mostra anche un'implementazione standard senza l'annotazione.
@Getter / @Setter Genera getter e setter per i campi privati.

@Getter 
@Setter 
private String name = "name";
@NonNull Utilizzato per affermare che i campi non sono nulli quando viene istanziato un oggetto. In caso contrario, viene generata un'eccezione NullPointerException .

public Example(@NonNull P p) {
 super("Hello");
 this.name = p.getName();
}

Lombok ha molte più annotazioni utili che vengono usate meno spesso. Abbiamo considerato le sue annotazioni più semplici. Puoi leggere di più sul progetto sul sito ufficiale .