środa, 19 maja 2010

Adnotacje

Adnotacje (ang. annotations) są dostępne w javie od wersji 1.5 i służą do opisywania klas. W poniższym artykule opowiem jak szybko stworzyć i wykorzystać własne adnotacje.

Tworzenie adnotacji
Definicja pustej adnotacji nie różni się specjalnie od definicji pustego interfejsu. Pomijając znaczek @ w słówku @interface w zasadzie nie ma żadnej różnicy.
package com.blogspot.mkorwel.annotation;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationMethod {

}
Stworzenie adnotacji wymaga jeszcze użycia metaadnotacji. Poniżej umieszczam krótki opis:
  • @Target określa miejsce stosowania adnotacji
  • @Retention określa trwałość adnotacji
  • @Documented ujęcie danej adnotacji w dokumencie Javadoc
  • @Inherited zezwolenie na dziedziczenie adnotacji w podklasach

Możliwe argumenty dla metaadnotacji @Target to:
  • ElementType.TYPE - w deklaracji klasy, interfejsu, adnotacji, enum
  • ElementType.CONSTRUCTOR - w deklaracji konstruktora
  • ElementType.FIELD - w deklaracji pola
  • ElementType.LOCAL_VARIABLE - w deklaracji zmiennej lokalnej
  • ElementType.METHOD - w deklaracji metody
  • ElementType.PACKAGE - w deklaracji pakietu
  • ElementType.PARAMETER - w deklaracji parametru

Możliwe argumenty dla metaadnotacji @Retention to:
  • RetentionPolicy.SOURCE - adnotacje unieważnione przez kompilator
  • RetentionPolicy.CLASS - adnotacje widoczne w plikach klas, unieważnione przez maszynę wirtualną
  • RetentionPolicy.RUNTIME - adnotacje podtrzymywane w maszynie wirtualnej w czasie wykonania, a więc nadające się do odczytu za pośrednictwem refleksji

Poniżej stworzymy jeszcze jedną adnotację która będzie używana przy deklaracji klas (@Target(ElementType.TYPE)). Adnotacja będzie zawierała dwa elementy. Poniżej kod:
package com.blogspot.mkorwel.annotation;

import java.lang.annotation.Documented;
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)
@Documented
public @interface MyAnnotationClass {

 public int id() default -1;
 
 public String name();
 
}
Elementy w adnotacjach deklarujemy podobnie do metod w intefejsie. Każdy element może mieć wartość domyślną, aby ustalić taką wartość używamy słówka default.

Wykorzystanie adnotacji
Po stworzeniu dwóch naszych adnotacji, możemy użyć ich w naszej klasie. Kod klasy nie jest zbyt skomplikowany, więc nie będę go opisywał.
package com.blogspot.mkorwel;

import com.blogspot.mkorwel.annotation.MyAnnotationClass;
import com.blogspot.mkorwel.annotation.MyAnnotationMethod;

@MyAnnotationClass(id = 1, name = "Mateusz")
public class MyClass {
 
 @MyAnnotationMethod
 public void test(){
  
 }

}

Kiedy mamy już adnotacje i klasę która jest nimi opisana, możemy stworzyć klasę która wykorzysta nasze adnotacje i wypisze komunikat na ekranie. Kod klasy która to robi znajduje się poniżej:
package com.blogspot.mkorwel;

import com.blogspot.mkorwel.annotation.MyAnnotationClass;

/**
 * 
 * @author Mateusz Korwel
 * 
 */
public class Test {

 public static void main(String[] args) {

  // tworzenie klasy
  MyClass myClass = new MyClass();
  Class clazz = myClass.getClass();

  // pobranie adnotacji w klasie
  for (int i = 0; i < clazz.getAnnotations().length; i++) {
   // wypisanie adnotacji
   System.out.println("Nazwa adnotacji: " + clazz.getAnnotations()[i]);
   System.out.println("Wartość atrybutu id: "
     + ((MyAnnotationClass) clazz.getAnnotations()[i]).id());
   System.out.println("Wartość atrybutu name: "
     + ((MyAnnotationClass) clazz.getAnnotations()[i]).name());
  }

  // pobranie wszystkich publicznych/pakietowych metod z klasy MyClass
  for (int i = 0; i < clazz.getMethods().length; i++) {
   // pobranie wszystkich adnotacji przypisanych do metody
   for (int j = 0; j < clazz.getMethods()[i].getAnnotations().length; j++) {
    // nazwa metody z adnotacją
    System.out.println("\nNazwa metody z adnotacją: "
      + clazz.getMethods()[i].getName());
    // wypisanie adnotacji
    System.out.println("Nazwa adnotacji: "
      + clazz.getMethods()[i].getAnnotations()[j]);
   }
  }
 }
}
Krótko opiszę co powyższa klasa robi. W pierwszej pętli for pobieramy wszystkie adnotacje które są przypisane do klasy. W naszym przypadku jest to tylko jedna adnotacja @MyAnnotationClass z dwoma elementami które zostaną również wypisane. Druga pętla for pobiera metody jakie znajdują się w klasie, a następnie pobiera adnotacje przypisane do kolejnych metod. W naszym przypadku będzie wypisana jedna metoda test() z jedną adnotacją @MyAnnotationMethod.

Brak komentarzy:

Prześlij komentarz