Principalul beneficiu al adnotărilor nu vine din utilizarea celor standard care sunt deja în JDK. În același timp, rareori este nevoie să vă creați propria adnotare. Dar dacă dezvoltăm un sistem mare sau creăm o bibliotecă separată, atunci la nivel arhitectural, implementarea propriei noastre adnotări va aduce cu siguranță dividende.

Să încercăm să creăm o adnotare.

Pentru a face acest lucru, creați un fișier, dar în loc să scrieți class sau interface , scrieți @interface . Acesta va fi fișierul pentru adnotarea noastră. Structura internă a unei adnotări este similară cu cea a unei interfețe.


public @interface Sum {
   int sum() default 0;
}

@interface indică faptul că aceasta este o adnotare,
implicit spune că parametrul va avea o anumită valoare implicită.

Ta-da! Am creat o adnotare! Teoretic îl putem folosi deja, dar mai întâi ar fi mai bine să îl configuram.

Fără configurație, adnotarea noastră poate fi aplicată la orice (la clase, metode, atribute etc.), așa că nu are sens să o folosim în acest moment. Oricât de ciudat ar părea, adnotarea noastră trebuie să fie adnotată cu alte adnotări!

Să începem cu @Target .

Adnotarea @Target (relevantă începând cu Java 1.5) restricționează capacitatea de a aplica o adnotare. Pentru a limita utilizarea la un anumit nivel, trebuie să transmitem un argument adnotării @Target pentru a indica ce tipuri poate fi aplicat. Iată câteva dintre tipurile frecvent utilizate:

@Target(ElementType.PACKAGE) pentru pachete
@Target(ElementType.TYPE) pentru cursuri
@Target(ElementType.CONSTRUCTOR) pentru constructori
@Target(ElementType.METHOD) pentru metode
@Target(ElementType.FIELD) pentru atribute (variabile) dintr-o clasă
@Target(ElementType.PARAMATER) pentru parametrii metodei
@Target(ElementType.LOCAL_VARIABLE) pentru variabilele locale

Dacă aveți nevoie de o adnotare pentru mai multe tipuri, atunci puteți trece mai multe argumente ca matrice:


@Target({ ElementType.PARAMETER, ElementType.LOCAL_VARIABLE })

Următoarea parte importantă a configurației este adnotarea @Retention .

Această adnotare indică părțile ciclului de viață a codului în care adnotarea noastră va fi disponibilă:

RetentionPolicy.SOURCE Adnotările marcate cu politica de păstrare SOURCE sunt eliminate în timpul execuției.
RetentionPolicy.CLASS Adnotările marcate cu politica de reținere CLASS sunt scrise în fișierul .class , dar sunt eliminate în timpul execuției.
RetentionPolicy.RUNTIME Adnotările marcate cu politica de păstrare RUNTIME persistă în timpul rulării și pot fi accesate în programul nostru în timpul rulării.

Mai sunt câteva adnotări pe care le puteți folosi pentru configurare:

Adnotare Valoare
@Mostenit Indică faptul că o clasă derivată moștenește implementarea adnotării de către o clasă părinte.
@Documentat Aceasta indică faptul că adnotarea va fi inclusă în documentația Javadoc generată.

Acum să încercăm să creăm propria noastră adnotare.

Vom crea o adnotare care este pentru clase și metode și care conține informații despre autorul și versiunea codului:


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

Ne putem aplica adnotarea la metode și clase. Metadatele adnotărilor noastre vor fi disponibile în timpul executării. Fiți atenți la parametrii adnotărilor noastre: putem furniza două argumente (autor și versiune), sau le putem omite. Dacă le omitem, atunci se vor folosi valorile implicite specificate ( implicit „Author” și implicit „0.0” ).

Este de remarcat faptul că nu trebuie să specificăm o valoare implicită pentru parametri. În acest caz, parametrul devine obligatoriu.

Când transmitem argumente, trebuie să specificăm parametrul corespunzător folosind notația value = "value" . Parametrul trebuie întotdeauna denumit explicit, chiar dacă adnotarea are un singur parametru.

Să aplicăm adnotarea noastră la câteva clase:


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