sabato 27 agosto 2011

Un esempio di utilizzo delle annotazioni in Java


In questo post vediamo un esempio di creazione e di utilizzo delle annotazioni in Java.
Introdotte fin dalla versione 1.5, le annotazioni sono utilizzate in maniera massiccia dagli Ejb 3.0 in poi e costituiscono un punto di forza anche di JPA, l’interfaccia per la persistenza dati introdotta dalla Sun.
Tuttavia possono anche essere utilizzate e create dagli sviluppatori per le più svariate ragioni, sia per commentare meglio il codice che per utilizzarle via reflection.
Vediamo un semplice esempio.
Definiamo una annotazione (n.b. si definiscono come le interfacce)

package it.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
public String nome();
public String versione();

}




 






Le regole da seguire per i metodi definiti all’interno di una annotation sono le seguenti:
  1. Per definire una annotazione bisogna anteporre @interface al nome dell’annotazione;
  2. Le dichiarazioni dei metodi non devono contenere parametri di input;
  3. Le dichiarazioni dei metodi non devono dichiarare la throw di una Exception;
  4. I tipi di ritorno devono essere primitive,String,class enum oppure array dei tipi precedentemente elencati.
  
L’annotation @Target indica a cosa posso applicare l’annotazione all’interno di una classe Java.
I valori ammissibili sono

  1. TYPE: Classi, interfacce, oppure  enum (non annotation)
  2. FIELD: campi  (inclusi valori enum)
  3. METHOD: metodi (non  costruttori)
  4. PARAMETER: parametri di un metodo
  5. CONSTRUCTOR: costruttori
  6. LOCAL_VARIABLE: variabile locale
  7. ANNOTATION_TYPE: tipo annotation
  8. PACKAGE: java package

Se non mettiamo nulla l’annotazione può essere utilizzata ovunque.
NB: è un errore specificare più volte lo stesso valore , ad esempio @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) non compila.

L’annotation @Retention indica invece letteralmente per quanto tempo devono essere “mantenute” (to retain in inglese significa appunto mantenere).
I valori ammissibili sono:

  1. RUNTIME, indica che il valore dell’annotazione è visibile nel compilato e accedibile a runtime dalla JVM;
  2. CLASS, indica che il valore dell’annotazione è visibile nel compilato ma non accedibile a Runtime;
  3. SOURCE, indica che il valore dell’annotazione non è visibile nel compilato né accedibile a RunTime.

Il valore di default è class.
Di seguito vediamo come via reflection è possibile ispezionare le annotazioni presenti su una classe e quindi, una volta trovata l’annotazione di nostro interesse stamparne a video i valori.


import java.lang.annotation.Annotation;
@Info(nome="mario rossi",versione="1.0")
public class InfoTest {
public static void main(String[] args) throws Exception{
      Annotation[] annotazioni=InfoTest.class.getAnnotations();
      for(Annotation ann: annotazioni){
            if(ann instanceof Info){
                  Info i=(Info)ann;
                  System.out.println(i.nome());
                  System.out.println(i.versione());
            }
      }
}
}

 


Se eseguiamo il codice il risultato è il seguente:

mario rossi
1.0

Per capire meglio l’importanza e il significato dell’annotazione @Retention proviamo adesso a cambiare il valore da RUNTIME a CLASS.

Eseguendo la nostra classe InfoTest vediamo che in output non è stampato nulla, in quanto l’annotazione non è visibile a runtime alla JVM.

Se decompiliamo il codice vediamo che nella classe InfoTest l’annotazione @Info(nome=”mario rossi”,versione=”1.0”) è presente.
Se modifichamo ancora cambiando il valore di @Retention da CLASS a SOURCE oltre a non avere stampato nulla in output se decompiliamo il .class della classe InfoTest non abbiamo più traccia dell’annotazione.








Nessun commento:

Posta un commento