Jūs, iespējams, esat saskāries ar situācijām, kurās jums ir nepieciešams sadarboties metadati (dati, kas apraksta citus datus) ar klasēm, metodēm un / vai citiem lietojuma elementiem. Piemēram, jūsu programmēšanas komandai var būt nepieciešams noteikt nepabeigtas klases lielā lietojumprogrammā. Katrā nepabeigtajā klasē metadatos, visticamāk, būs iekļauts izstrādātāja vārds, kas atbild par klases pabeigšanu, un paredzamais klases pabeigšanas datums.
Pirms Java 5 komentāri bija vienīgais elastīgais mehānisms, ko Java piedāvāja metadatu saistīšanai ar lietojumprogrammas elementiem. Tomēr komentāri ir slikta izvēle. Tā kā kompilators tos ignorē, izpildes laikā komentāri nav pieejami. Pat ja tie būtu pieejami, teksts būtu parsēts, lai iegūtu izšķirošus datu objektus. Nenormizējot datu vienību norādīšanu, var izrādīties, ka šos datu vienumus nav iespējams parsēt.
lejupielādēt Iegūt kodu Lejupielādējiet avota kodu piemēriem šajā Java 101 apmācībā. Izveidoja Džefs Frīzens.Nestandarta anotāciju mehānismi
Java nodrošina nestandarta mehānismus metadatu saistīšanai ar lietojumprogrammas elementiem. Piemēram, īslaicīgs
rezervēts vārds ļauj jums anotēt (saistīt datus ar) laukus, kas jāizslēdz sērijveidošanas laikā.
Java 5 visu mainīja, ieviešot anotācijas, standarta mehānisms metadatu saistīšanai ar dažādiem lietojuma elementiem. Šis mehānisms sastāv no četrām sastāvdaļām:
- An
@interface
anotāciju veidu deklarēšanas mehānisms. - Meta-anotāciju veidi, kurus varat izmantot, lai identificētu lietojumprogrammas elementus, uz kuriem attiecas anotācijas tips; lai identificētu anotācija (anotācijas veida gadījums); un vēl.
- Atbalsts anotāciju apstrādei, izmantojot Java Reflection API paplašinājumu (par to runāsim nākamajā rakstā), kuru varat izmantot, lai atklātu programmas izpildlaika anotācijas, un vispārinātu rīku anotāciju apstrādei.
- Standarta anotāciju veidi.
Es paskaidrošu, kā izmantot šos komponentus, strādājot šajā rakstā.
Anotāciju veidu deklarēšana ar @interface
Anotācijas veidu varat deklarēt, norādot @
simbols, kam seko simbols interfeiss
rezervēts vārds un identifikators. Piemēram, 1. sarakstā tiek deklarēts vienkāršs anotācijas veids, kuru varat izmantot, lai anotētu pavedienam drošu kodu.
1. saraksts:ThreadSafe.java
public @interface ThreadSafe {}
Pēc šī anotācijas veida deklarēšanas pievienojiet metodes, kuras jūs uzskatāt par drošām ar pavedieniem, ar šāda veida gadījumiem, veicot iepriekšēju sagatavošanu @
uzreiz seko tipa nosaukums, līdz metodes galvenēm. 2. saraksts piedāvā vienkāršu piemēru, kur galvenais ()
metode ir anotēta @ThreadSafe
.
2. saraksts:AnnDemo.java
(1. versija)
publiskā klase AnnDemo {@ThreadSafe public static void main (String [] args) {}}
ThreadSafe
gadījumi nepiedāvā citus metadatus kā anotācijas tipa nosaukumu. Tomēr jūs varat piegādāt metadatus, šim tipam pievienojot elementus, kur elements ir metodes galvene, kas ievietota anotācijas tipa pamattekstā.
Uz elementiem attiecas ne tikai koda pamatteksti, bet arī šādi ierobežojumi:
- Metodes galvene nevar deklarēt parametrus.
- Metodes galvene nevar nodrošināt klauzulu “throws”.
- Metodes galvenes atgriešanās tipam jābūt primitīvam (piem.,
int
),java.lang.Strings
,java.lang.Class
, uzskaitījums, anotācijas tips vai viena no šiem veidiem masīvs. Atgriešanas tipam nevar norādīt citu veidu.
Kā vēl vienu piemēru 3. sarakstā ir norādīts a Darīt
anotācijas tips ar trim elementiem, kas identificē konkrētu kodēšanas darbu, norādot datumu, kad darbs jāpabeidz, un nosaucot kodētāju, kurš ir atbildīgs par darba pabeigšanu.
3. saraksts:ToDo.java
(1. versija)
public @interface ToDo {int id (); Stīgu finišsDatums (); Stīgu kodētājs () noklusējums "n / a"; }
Ņemiet vērā, ka katrs elements nedeklarē nevienu parametru (-us) vai met klauzulu, tam ir likumīgs atgriešanās veids (int
vai Stīga
) un beidzas ar semikolu. Arī pēdējais elements atklāj, ka var norādīt noklusējuma atgriešanās vērtību; šī vērtība tiek atgriezta, ja anotācijā elementam netiek piešķirta vērtība.
Uzskaitot 4 lietojumus Darīt
anotēt nepabeigtu klases metodi.
4. saraksts:AnnDemo.java
(2. versija)
publiskā klase AnnDemo {public static void main (String [] args) {Stīgu [] pilsētas = {"Ņujorka", "Melburna", "Pekina", "Maskava", "Parīze", "Londona"}; kārtot (pilsētas); } @ToDo (id = 1000, finishDate = "10.10.2019., Coder =" John Doe ") static void sort (Object [] objekti) {}}
4. saraksts katram elementam piešķir metadatu vienumu; piemēram, 1000
tiek piešķirts id
. Atšķirībā no kodētājs
, id
un finishDate
elementi ir jānorāda; pretējā gadījumā sastādītājs ziņos par kļūdu. Kad kodētājs
nav piešķirta vērtība, tā uzņemas noklusējumu "n / a"
vērtība.
Java nodrošina īpašu Virknes vērtība ()
elements, ko var izmantot, lai atgrieztu ar komatu atdalītu metadatu vienumu sarakstu. 5. saraksts parāda šo elementu atjaunotajā versijā Darīt
.
5. saraksts:ToDo.java
(2. versija)
public @interface ToDo {Virknes vērtība (); }
Kad vērtība ()
ir vienīgais anotācijas veida elements, jums tas nav jānorāda vērtība
un =
piešķirot operatoram virkni šim elementam. 6. saraksts parāda abas pieejas.
6. saraksts:AnnDemo.java
(3. versija)
publiskā klase AnnDemo {public static void main (String [] args) {Stīgu [] pilsētas = {"Ņujorka", "Melburna", "Pekina", "Maskava", "Parīze", "Londona"}; kārtot (pilsētas); } @ToDo (value = "1000,10 / 10/2019, John Doe") static void sort (Object [] objekti) {} @ToDo ("1000,10 / 10/2019, John Doe") statiskā būla meklēšana ( Object [] objekti, Object key) {return false; }}
Metanotāciju veidu izmantošana - elastības problēma
Varat anotēt veidus (piemēram, klases), metodes, lokālos mainīgos un daudz ko citu. Tomēr šī elastība var būt problemātiska. Piemēram, jūs varētu vēlēties ierobežot Darīt
tikai uz metodēm, taču nekas neliedz to izmantot citu lietojumprogrammu elementu anotēšanai, kā parādīts 7. sarakstā.
7. saraksts:AnnDemo.java
(4. versija)
@ToDo ("1000,10 / 10/2019, John Doe") publiskās klases AnnDemo {public static void main (String [] args) {@ToDo (value = "1000,10 / 10/2019, John Doe") virkne [] pilsētas = {"Ņujorka", "Melburna", "Pekina", "Maskava", "Parīze", "Londona"}; kārtot (pilsētas); } @ToDo (value = "1000,10 / 10/2019, John Doe") static void sort (Object [] objekti) {} @ToDo ("1000,10 / 10/2019, John Doe") statiskā būla meklēšana ( Object [] objekti, Object key) {return false; }}
7. sarakstā Darīt
tiek izmantots arī, lai anotētu AnnDemo
klase un pilsētās
vietējais mainīgais. Šo kļūdaino anotāciju klātbūtne var mulsināt kādu, kurš pārskata jūsu kodu, vai pat jūsu pašu anotāciju apstrādes rīkus. Laikā, kad jums ir jāsamazina anotācijas veida elastība, Java piedāvā Mērķis
anotācijas veids java.lang.annotation
iepakojums.
Mērķis
ir meta-anotācijas veids - anotācijas tips, kura anotācijās anotēti anotāciju tipi, atšķirībā no meta-anotāciju tipa, kura anotācijās tiek anotēti lietojuma elementi, piemēram, klases un metodes. Tas identificē lietojuma elementu veidus, kuriem piemērojams anotācijas tips. Šos elementus identificē ar Mērķis
’S ElementValue [] vērtība ()
elements.
java.lang.annotation.ElementType
ir enums, kura konstantes apraksta lietojuma elementus. Piemēram, BŪVNIEKS
attiecas uz konstruktoriem un PARAMETRS
attiecas uz parametriem. 8 refaktoru saraksts 5 saraksts Darīt
anotācijas veids, lai to ierobežotu tikai ar metodēm.
8. saraksts:ToDo.java
(3. versija)
importēt java.lang.annotation.ElementType; importēt java.lang.annotation.Target; @Target ({ElementType.METHOD}) public @interface ToDo {String value (); }
Ņemot vērā pārstrādāto Darīt
anotācijas veids, mēģinājums sastādīt 7. sarakstu tagad rada šādu kļūdas ziņojumu:
AnnDemo.java:1: kļūda: anotācijas veids nav piemērojams šāda veida deklarācijām @ToDo ("1000,10 / 10/2019, John Doe") ^ AnnDemo.java:6: kļūda: anotācijas veids nav piemērojams šāda veida deklarācijām deklarācija @ToDo (vērtība = "1000,10 / 10/2019, John Doe") ^ 2 kļūdas
Papildu metanotāciju veidi
Java 5 ieviesa trīs papildu meta-anotāciju veidus, kas ir atrodami java.lang.annotation
iepakojums:
Saglabāšana
norāda, cik ilgi jāsaglabā anotācijas ar anotēto tipu. Šis veids ir saistītsjava.lang.annotation.RetentionPolicy
enum pasludina konstantesKLASE
(kompilators ieraksta anotācijas klases failā; virtuālā mašīna tās nesaglabā, lai saglabātu atmiņu - noklusējuma politika),RUNTIME
(kompilators ieraksta anotācijas klases failā; virtuālā mašīna tās saglabā) unAVOTS
(sastādītājs izmet anotācijas).Dokumentēts
norāda, kaDokumentēts
-nototētās anotācijas dokumentējavadoc
un tamlīdzīgi rīki.Mantots
norāda, ka anotācijas tips tiek automātiski pārmantots.
Java 8 ieviesa java.lang.annotation. Atkārtojams
meta-anotācijas veids. Atkārtojams
tiek izmantots, lai norādītu, ka anotācijas tips, kura deklarāciju tā (meta-) anotē, ir atkārtojams. Citiem vārdiem sakot, lietojumprogrammas elementam varat piemērot vairākas anotācijas no tā paša atkārtojamās anotācijas veida, kā parādīts šeit:
@ToDo (value = "1000,10 / 10/2019, John Doe") @ToDo (value = "1001,10 / 10/2019, Kate Doe") static void sort (Object [] objekti) {}
Šis piemērs to pieņem Darīt
ir anotēta ar Atkārtojams
anotācijas veids.
Notiek anotāciju apstrāde
Anotācijas ir paredzētas apstrādei; pretējā gadījumā viņiem nav jēgas. Java 5 paplašināja Reflection API, lai palīdzētu jums izveidot savus anotāciju apstrādes rīkus. Piemēram, Klase
paziņo Anotācija [] getAnnotations ()
metode, kas atgriež masīvu java.lang.Anotācija
gadījumi, kas apraksta anotācijas, kas atrodas elementā, kuru aprakstījis Klase
objekts.
9. saraksts parāda vienkāršu lietojumprogrammu, kas ielādē klases failu, iztaujā tās metodes Darīt
anotācijas un izvada katras atrastās anotācijas komponentus.
9. saraksts:AnnProcDemo.java
importēt java.lang.reflect.Method; public class AnnProcDemo {public static void main (String [] args) izmet izņēmumu {if (args.length! = 1) {System.err.println ("use: java AnnProcDemo classfile"); atgriešanās; } Metode [] metodes = Class.forName (argumentē [0]). GetMethods (); for (int i = 0; i <metodes.length; i ++) {if (metodes [i] .isAnnotationPresent (ToDo.class)) {ToDo todo = metodes [i] .getAnnotation (ToDo.class); Stīgu [] komponenti = todo.value (). Split (","); System.out.printf ("ID =% s% n", komponenti [0]); System.out.printf ("Finish date =% s% n", komponenti [1]); System.out.printf ("Coder =% s% n% n", komponenti [2]); }}}}
Pārbaudot, vai ir norādīts tieši viens komandrindas arguments (klases faila identificēšana), galvenais ()
ielādē klases failu caur Class.forName ()
, izsauc getMethods ()
atgriezt masīvu java.lang.reflect.Metode
objekti, kas identificē visus publiski
metodes klases failā un apstrādā šīs metodes.
Metodes apstrāde sākas ar atsaukšanos Metode
’S boolean isAnnotationPresent (klases annotationClass)
metode, lai noteiktu, vai anotācija aprakstīta ar ToDo.klase
ir klāt metodei. Ja tā, Metode
’S T getAnnotation (klases annotationClass)
metodi, lai iegūtu anotāciju.
The Darīt
Apstrādātas anotācijas ir tās, kuru tipi deklarē vienu Virknes vērtība ()
elements (skat. 5. sarakstu). Tā kā šī elementa metadati, kuru pamatā ir virkne, ir atdalīti ar komatu, tie jāsadala komponentu vērtību masīvā. Pēc tam tiek piekļūta katrai no trim komponentu vērtībām un izvadīta.
Apkopojiet šo avota kodu (javac AnnProcDemo.java
). Lai varētu palaist lietojumprogrammu, jums būs nepieciešams piemērots klases fails ar @Darīt
anotācijas par to publiski
metodes. Piemēram, jūs varētu modificēt 6. sarakstu AnnDemo
iekļaujamais pirmkods publiski
tās kārtot ()
un Meklēt()
metodes galvenes. Jums būs nepieciešami arī saraksti 10 Darīt
anotācijas tips, kuram nepieciešams RUNTIME
saglabāšanas politika.
10. saraksts:ToDo.java
(4. versija)
importēt java.lang.annotation.ElementType; importēt java.lang.annotation.Retention; importēt java.lang.annotation.RetentionPolicy; importēt java.lang.annotation.Target; @Target ({ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) public @interface ToDo {String value (); }
Apkopo modificēto AnnDemo.java
un 10. saraksts, un izpildiet šādu komandu apstrādei AnnDemo
’S Darīt
anotācijas:
java AnnProcDemo AnnDemo
Ja viss norit labi, jums jāievēro šāda izeja:
ID = 1000 beigu datums = 10.10.2019. Coder = John Doe ID = 1000 beigu datums = 2019.10.10 Coder = John Doe
Apstrādājot anotācijas ar apt un Java kompilatoru
Java 5 ieviesa trāpīgs
rīks anotāciju apstrādei vispārīgā veidā. Java 6 migrēja trāpīgs
Funkcionalitāti javac
kompilatora rīks, un Java 7 ir novecojis trāpīgs
, kas pēc tam tika noņemts (sākot ar Java 8).
Standarta anotāciju veidi
Kopā ar Mērķis
, Saglabāšana
, Dokumentēts
, un Mantots
, Ieviesta Java 5 java.lang. Novecojis
, java.lang. Pārcelt
, un java.lang.SuppressWarnings
. Šie trīs anotāciju veidi ir paredzēti lietošanai tikai sastādītāja kontekstā, tāpēc ir iestatīta to saglabāšanas politika AVOTS
.