Programmēšana

Kā aprakstīt Java kodu ar anotācijām

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īts java.lang.annotation.RetentionPolicy enum pasludina konstantes KLASE (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ā) un AVOTS (sastādītājs izmet anotācijas).
  • Dokumentēts norāda, ka Dokumentē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īgsFunkcionalitā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.

Novecojis

$config[zx-auto] not found$config[zx-overlay] not found