Programavimas

Kaip apibūdinti Java kodą su anotacijomis

Tikriausiai esate susidūrę su situacijomis, kai jums reikia bendrauti metaduomenys (duomenys, apibūdinantys kitus duomenis) su klasėmis, metodais ir (arba) kitais programos elementais. Pavyzdžiui, jūsų programavimo komandai gali reikėti nustatyti nebaigtas klases didelėje programoje. Kiekvienos nebaigtos klasės metaduomenyse greičiausiai bus nurodytas kūrėjo, atsakingo už klasės baigimą, vardas ir numatoma klasės baigimo data.

Prieš „Java 5“ komentarai buvo vienintelis lankstus mechanizmas, kurį „Java“ turėjo pasiūlyti susiedama metaduomenis su programos elementais. Tačiau komentarai yra prastas pasirinkimas. Kadangi kompiliatorius jų nepaiso, vykdymo metu komentarai nėra prieinami. Net jei jų būtų, tekstas turėtų būti išanalizuotas, kad gautumėte svarbiausius duomenų elementus. Nenormavus duomenų elementų nurodymo, šių duomenų elementų gali būti neįmanoma išanalizuoti.

atsisiųsti Gauti kodą Atsisiųskite šios „Java 101“ mokymo programos pavyzdžių šaltinio kodą. Sukūrė Jeffas Friesenas.

Nestandartiniai anotacijų mechanizmai

„Java“ pateikia nestandartinius metaduomenų susiejimo su programos elementais mechanizmus. Pavyzdžiui, trumpalaikis rezervuotas žodis leidžia komentuoti (susieti duomenis su) laukais, kurie turi būti pašalinti serijos metu.

„Java 5“ viską pakeitė pristatydama anotacijos, standartinis metaduomenų susiejimo su įvairiais programos elementais mechanizmas. Šis mechanizmas susideda iš keturių komponentų:

  • An @interface anotacijų tipų deklaravimo mechanizmas.
  • Meta-anotacijų tipai, kuriuos galite naudoti norėdami nustatyti programos elementus, kuriems taikomas anotacijų tipas; nustatyti gyvenimo trukmę anotacija (anotacijos tipo egzempliorius); ir dar.
  • Anotacijų apdorojimo palaikymas per „Java Reflection“ API plėtinį (apie tai bus kalbama būsimame straipsnyje), kurį galite naudoti norėdami atrasti programos vykdymo laiko anotacijas, ir apibendrintą įrankį anotacijoms apdoroti.
  • Standartiniai anotacijų tipai.

Paaiškinsiu, kaip naudoti šiuos komponentus, kai dirbame šiame straipsnyje.

Anotacijų tipų deklaravimas naudojant @interface

Anotacijos tipą galite deklaruoti nurodydami @ simbolis iškart po jo sąsaja rezervuotas žodis ir identifikatorius. Pvz., 1 sąrašas skelbia paprastą komentarų tipą, kurį galite naudoti anotuodami saugų siūlą kodą.

1 sąrašas:„ThreadSafe.java“

public @interface „ThreadSafe“ {}

Deklaravę šį anotacijos tipą, prieš pateikdami metodo, kurį laikote saugiu siūlais, prieš šio tipo egzempliorius @ iškart po tipo pavadinimo bus nurodytos metodo antraštės. 2 sąraše pateikiamas paprastas pavyzdys, kai pagrindinis () metodas yra anotuotas @ThreadSafe.

2 sąrašas:AnnDemo.java (1 versija)

public class AnnDemo {@ThreadSafe public static void main (String [] argumentuoja) {}}

„ThreadSafe“ egzemplioriai nepateikia jokių kitų metaduomenų, išskyrus anotacijos tipo pavadinimą. Tačiau galite pateikti metaduomenis pridėdami elementus prie šio tipo, kur elementas yra metodo antraštė, dedama į anotacijos tipo turinį.

Be to, kad elementai neturi kodų, jiems taikomi šie apribojimai:

  • Metodo antraštė negali deklaruoti parametrų.
  • Metodo antraštėje negalima pateikti metimo sąlygos.
  • Metodo antraštės grąžinimo tipas turi būti primityvus (pvz., tarpt), java.lang.Stringas, java.lang.Klasė, sąrašas, anotacijos tipas arba vieno iš šių tipų masyvas. Grąžinimo tipui negalima nurodyti jokio kito tipo.

Kaip kitą pavyzdį 3 sąraše pateikiama a Daryti anotacijos tipas su trimis elementais, identifikuojančiais tam tikrą kodavimo užduotį, nurodant datą, kada turi būti baigta užduotis, ir įvardijamas koduotojas, atsakingas už darbo atlikimą.

3 sąrašas:ToDo.java (1 versija)

public @interface ToDo {int id (); Styginių apdailaData (); String coder () numatytasis „n / a“; }

Atminkite, kad kiekvienas elementas nedeklaruoja jokio parametro (-ų) ar meta sąlygą, turi teisinį grąžinimo tipą (tarpt arba Stygos) ir baigiasi kabliataškiu. Be to, paskutinis elementas atskleidžia, kad galima nurodyti numatytąją grąžos vertę; ši vertė grąžinama, kai anotacija nepriskiria elementui vertės.

Išvardijami 4 naudojimo būdai Daryti anotuoti nebaigtą klasės metodą.

4 sąrašas:AnnDemo.java (2 versija)

public class AnnDemo {public static void main (String [] args) {Styginių [] miestai = {"Niujorkas", "Melburnas", "Pekinas", "Maskva", "Paryžius", "Londonas"}; rūšiuoti (miestai); } @ToDo (id = 1000, finishDate = "2019-10-10", coder = "John Doe") statinis tuštumas (Object [] objektai) {}}

4 sąrašas priskiria metaduomenų elementą kiekvienam elementui; pavyzdžiui, 1000 yra priskirtas id. Skirtingai koduotojas, id ir finishDate elementai turi būti nurodyti; kitaip kompiliatorius praneš apie klaidą. Kada koduotojas nėra priskirta reikšmė, ji prisiima numatytąją reikšmę „nėra“ vertė.

„Java“ suteikia specialų Eilutės reikšmė() elementas, kuris gali būti naudojamas grąžinant kableliais atskirtą metaduomenų elementų sąrašą. 5 sąrašas parodo šį elementą atnaujintoje versijoje Daryti.

5 sąrašas:ToDo.java (2 versija)

public @interface ToDo {String value (); }

Kada vertė () yra vienintelis anotacijos tipo elementas, jums nereikia nurodyti vertė ir = priskyrimo operatorius, kai šiam elementui priskiriama eilutė. 6 sąrašas parodo abu metodus.

6 sąrašas:AnnDemo.java (3 versija)

public class AnnDemo {public static void main (String [] args) {Styginių [] miestai = {"Niujorkas", "Melburnas", "Pekinas", "Maskva", "Paryžius", "Londonas"}; rūšiuoti (miestai); } @ToDo (value = "1000,10 / 10/2019, John Doe") static void sort (Object [] Objects) {} @ToDo ("1000,10 / 10/2019, John Doe") statinė loginė paieška ( Object [] objektai, Object key) {return false; }}

Naudojant meta-anotacijų tipus - lankstumo problema

Galite komentuoti tipus (pvz., Klases), metodus, vietinius kintamuosius ir dar daugiau. Tačiau šis lankstumas gali būti problemiškas. Pavyzdžiui, galbūt norėsite apriboti Daryti tik metodams, tačiau niekas netrukdo jį naudoti komentuojant kitus programos elementus, kaip parodyta 7 sąraše.

7 sąrašas:AnnDemo.java (4 versija)

@ToDo ("1000,10 / 10/2019, John Doe") public class AnnDemo {public static void main (String [] args) {@ToDo (value = "1000,10 / 10/2019, John Doe") eilutė [] miestai = {"Niujorkas", "Melburnas", "Pekinas", "Maskva", "Paryžius", "Londonas"}; rūšiuoti (miestai); } @ToDo (value = "1000,10 / 10/2019, John Doe") static void sort (Object [] Objects) {} @ToDo ("1000,10 / 10/2019, John Doe") statinė loginė paieška ( Object [] objektai, Object key) {return false; }}

7 sąraše Daryti taip pat naudojamas anotuoti AnnDemo klasė ir miestuose vietinis kintamasis. Šių klaidingų komentarų buvimas gali suklaidinti asmenį, peržiūrintį jūsų kodą, ar net jūsų pačių komentarų apdorojimo įrankius. Tais atvejais, kai reikia susiaurinti anotacijos tipo lankstumą, „Java“ siūlo Taikinys anotacijos tipas java.lang.notacija pakuotė.

Taikinys yra meta-anotacijos tipas - anotacijos tipas, kurio anotacijose anotuojami anotacijų tipai, priešingai nei ne meta-anotacijų tipams, kurių anotacijose yra anotuojami taikymo elementai, pvz., Klasės ir metodai. Jis nurodo programų elementų rūšis, kurioms taikomas anotacijos tipas. Šiuos elementus identifikuoja Taikinys’S ElementValue [] vertė () elementas.

java.lang.annotation.ElementType yra enumas, kurio konstantos apibūdina taikymo elementus. Pavyzdžiui, KONSTRUKTORIUS taikoma konstruktoriams ir PARAMETRAS taikoma parametrams. 8 refaktorių sąrašas 5 sąrašas Daryti anotacijos tipas, kad apribotumėte tik metodus.

8 sąrašas:ToDo.java (3 versija)

importuoti java.lang.annotation.ElementType; importuoti java.lang.annotation.Target; @Target ({ElementType.METHOD}) public @interface ToDo {String value (); }

Atsižvelgiant į pertvarkytą Daryti komentaro tipas, bandant sudaryti 7 sąrašą dabar pateikiamas toks klaidos pranešimas:

AnnDemo.java:1: klaida: anotacijos tipas netaikomas šios rūšies deklaracijoms @ToDo ("1000,10 / 10/2019, John Doe") ^ AnnDemo.java:6: klaida: komentarų tipas netaikomas tokio tipo deklaracija @ToDo (vertė = "1000,10 / 10/2019, John Doe") ^ 2 klaidos

Papildomi meta-anotacijų tipai

„Java 5“ pristatė tris papildomus meta-anotacijų tipus, kurie yra java.lang.notacija paketas:

  • Išlaikymas nurodo, kiek laiko turi būti išsaugotos anotacijos su anotuotu tipu. Šis tipas yra susijęs java.lang.annotation.RetentionPolicy enumas skelbia konstantas KLASĖ (kompiliatorius įrašo anotacijas klasės faile; virtuali mašina jų nelaiko, kad išsaugotų atmintį - numatytoji politika), RUNTIME (kompiliatorius įrašo anotacijas klasės faile; virtualioji mašina jas išlaiko) ir ŠALTINIS (sudarytojas atmeta anotacijas).
  • Dokumentais rodo, kad Dokumentais- nepatvirtintos anotacijos turi būti dokumentuotos javadokas ir panašūs įrankiai.
  • Paveldėtas rodo, kad anotacijos tipas automatiškai paveldimas.

„Java 8“ pristatė java.lang.nototation.Kartojamas meta-anotacijos tipas. Pakartotinas yra naudojamas nurodyti, kad anotacijos tipas, kurio deklaraciją jis (meta-) komentuoja, yra pakartojamas. Kitaip tariant, programos elementui galite pritaikyti kelias anotacijas iš to paties pakartojamų komentarų tipo, kaip parodyta čia:

@ToDo (value = "1000,10 / 10/2019, John Doe") @ToDo (value = "1001,10 / 10/2019, Kate Doe") statinis niekinis rūšiavimas (objektai [] objektai) {}

Šis pavyzdys daro prielaidą Daryti buvo anotuotas Pakartotinas anotacijos tipas.

Apdorojamos anotacijos

Anotacijos yra skirtos apdoroti; kitaip nėra prasmės jų turėti. „Java 5“ išplėtė „Reflection“ API, kad padėtų jums sukurti savo anotacijų apdorojimo įrankius. Pavyzdžiui, Klasė pareiškia an Anotacija [] getAnnotations () metodas, kuris pateikia masyvą java.lang. Anotacija egzemplioriai, apibūdinantys anotacijas, nurodytas Klasė objektas.

9 sąraše pateikiama paprasta programa, įkelianti klasės failą, apklausianti jos metodus Daryti anotacijas ir pateikia kiekvienos rastos anotacijos komponentus.

9 sąrašas:AnnProcDemo.java

importuoti java.lang.reflect.Method; public class AnnProcDemo {public static void main (String [] args) meta išimtį {if (args.length! = 1) {System.err.println ("naudojimas: java AnnProcDemo classfile"); grįžti; } Metodas [] metodai = Class.forName (argumentai [0]). GetMethods (); for (int i = 0; i <metodai.length; i ++) {if (metodai [i] .isAnnotationPresent (ToDo.class)) {ToDo todo = metodai [i] .getAnnotation (ToDo.class); Styginių [] komponentai = todo.value (). Split (","); System.out.printf ("ID =% s% n", komponentai [0]); System.out.printf ("Baigimo data =% s% n", komponentai [1]); System.out.printf ("Koderis =% s% n% n", komponentai [2]); }}}}

Patikrinę, ar nurodytas tiksliai vienas komandinės eilutės argumentas (nustatantis klasės failą), pagrindinis () įkelia klasės failą per „Class.forName“ (), kviečia „getMethods“ () grąžinti masyvą java.lang. refleksija.Metodas objektai, identifikuojantys visus visuomenės metodus klasės faile ir apdoroja šiuos metodus.

Metodo apdorojimas prasideda iškviečiant Metodas’S boolean isAnnotationPresent (klasės anotacijaKlasė) metodas nustatyti, ar anotacija aprašyta ToDo.klasė yra metodas. Jei taip, Metodas’S „T getAnnotation“ („Class annotationClass“) metodas yra naudojamas anotacijai gauti.

Daryti apdorojamos anotacijos, kurių tipai skelbia vieną Eilutės reikšmė() elementą (žr. 5 sąrašą). Kadangi šio elemento eilutės metaduomenys yra atskirti kableliais, juos reikia padalyti į komponentų reikšmių masyvą. Tada pasiekiama ir išvedama kiekviena iš trijų komponentų reikšmių.

Sudarykite šį šaltinio kodą (javac AnnProcDemo.java). Kad galėtumėte paleisti programą, jums reikės tinkamo klasės failo @Daryti anotacijos visuomenės metodai. Pavyzdžiui, galite modifikuoti 6 sąrašą AnnDemo šaltinio kodą visuomenės jos rūšiuoti () ir Paieška() metodo antraštės. Jums taip pat reikės „Listing 10“ Daryti anotacijos tipas, kuriam reikalingas RUNTIME išlaikymo politika.

10 sąrašas:ToDo.java (4 versija)

importuoti java.lang.annotation.ElementType; importuoti java.lang.annotation.Retention; importuoti java.lang.annotation.RetentionPolicy; importuoti java.lang.annotation.Target; @Target ({ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) public @interface ToDo {String value (); }

Sudarykite modifikuotą AnnDemo.java ir „Listing 10“, ir vykdykite šią komandą, kad ją apdorotumėte AnnDemo’S Daryti anotacijos:

java AnnProcDemo AnnDemo

Jei viskas gerai, turėtumėte stebėti šį rezultatą:

ID = 1000 pabaigos data = 2019-10-10 Coder = John Doe ID = 1000 pabaigos data = 2019-10-10 Coder = John Doe

Apdorojimas su apt ir Java kompiliatoriumi

„Java 5“ pristatė taiklus įrankis anotacijoms apdoroti apibendrintai. „Java 6“ migravo taiklusFunkcionalumą javac kompiliatoriaus įrankis ir „Java 7“ nebenaudojamas taiklus, kuris vėliau buvo pašalintas (pradedant „Java 8“).

Standartiniai anotacijų tipai

Kartu su Taikinys, Išlaikymas, Dokumentaisir Paveldėtas, Pristatyta „Java 5“ java.lang.Nenaudojama, java.lang.Paisytiir java.lang.SuppressWarnings. Šie trys anotacijų tipai yra skirti naudoti tik kompiliatoriaus kontekste, todėl nustatyta jų išlaikymo politika ŠALTINIS.

Nebenaudojamas