Tworzenie adnotacji jest dość prostym procesem, choć ograniczonym pewnymi zasadami. Teraz musimy dowiedzieć się, jakie jest ich zastosowanie w praktyce.

Pamiętajmy jak tworzymy naszą adnotację.

Piszemy adnotację, która będzie adnotować klasy i metody oraz zawierać informacje o autorze i wersji:


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

Nasze zajęcia, do których dodaliśmy adnotację:


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

Jak możemy wykorzystać te dane na etapie działania programu?

Możesz wyodrębnić metadane z adnotacji za pomocą odbicia. Przypomnijmy sobie, czym jest refleksja. Jest to mechanizm służący do sprawdzania danych o programie podczas jego działania. Refleksja pozwala uzyskać informacje o polach, metodach, konstruktorach klas, a także o klasach.

Za pomocą refleksji przeczytamy adnotacje w klasie i wyświetlimy potrzebne nam informacje.

Rozpoznawanie danych z naszych zajęć w głównym :


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

Przekazujemy instancję naszej klasy do metody readMyClass w celu przetworzenia.

Ponadto do metody readAnnotation możemy przekazać zarówno klasę, jak i metodę . Więc zróbmy to: przekazujemy tam obiekt klasy i obiekt metody. Otrzymano obiekt, który implementuje kontrakt AnnotatedElement . Pozwala to pobrać z niego listę adnotacji i przeczytać informacje o każdej z nich.

Zauważ, że nie uzyskamy informacji bez sprawdzenia, czy adnotacja należy do naszego typu adnotacji ( if (annotation instanceof Info) ).

Na wyjściu otrzymujemy pełne informacje z adnotacji:

Class annotation.MyClass1
Szukaj adnotacji w java.lang.Class
Autor: Author
Wersja: 0.0
Szukaj adnotacji w java.lang.reflect.Method
Autor: Author
Wersja: 0.0

Class annotation.MyClass2
Szukaj adnotacji w java.lang.Class
Autor : Autor
Wersja : 2.0
Szukaj adnotacji w java.lang.reflect.Method
Autor: Anonimowa
Wersja: 0.0

Class annotation.MyClass3
Szukaj adnotacji w java.lang.Class
Autor: Anonimowa
Wersja: 2.0
Szukaj adnotacji w java.lang.reflect Metoda
Autor: Anonimowa
Wersja: 4.0

Tak więc z pomocą refleksji byliśmy w stanie wydobyć metainformacje.

Przyjrzyjmy się teraz przykładowi użycia adnotacji w celu ulepszenia kodu, w tym zwiększenia czytelności, szybkości i ogólnej jakości. Lombok nam w tym pomoże.

Lombok to wtyczka kompilatora, która wykorzystuje słowa kluczowe adnotacji, aby ukryć ogromną ilość kodu, rozszerzając język, upraszczając w ten sposób programowanie i dodając pewne funkcje.

Rozważmy przykład adnotacji z Lombok:

@ToString Generuje implementację metody toString() , która składa się z przejrzystej reprezentacji obiektu: nazwy klasy, wszystkich pól i ich wartości.

@ToString
public class Example
@EqualsAndHashCode Generuje implementacje equals i hashCode , które domyślnie używają pól niestatycznych i niestatycznych, ale można je konfigurować. Więcej szczegółów można znaleźć na stronie internetowej projektu . Przykład jest tam opisany przy użyciu @EqualsAndHashCode i bez niego ze standardową implementacją.
@Getter / @Setter Generuje metody pobierające i ustawiające dla pól prywatnych.

@Getter 
@Setter 
private String name = "name";
@NonNull Służy do potwierdzania, że ​​pola nie są puste, gdy obiekt jest tworzony. W przeciwnym razie zgłaszany jest wyjątek NullPointerException .

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

Lombok ma o wiele więcej przydatnych adnotacji, które są używane rzadziej. Rozważaliśmy prostą część jego adnotacji. Więcej o samym projekcie można przeczytać na oficjalnej stronie internetowej .