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ęsjava.lang.annotation.RetentionPolicy
enumas skelbia konstantasKLASĖ
(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, kadDokumentais
- nepatvirtintos anotacijos turi būti dokumentuotosjavadokas
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 taiklus
Funkcionalumą 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
, Dokumentais
ir Paveldėtas
, Pristatyta „Java 5“ java.lang.Nenaudojama
, java.lang.Paisyti
ir java.lang.SuppressWarnings
. Šie trys anotacijų tipai yra skirti naudoti tik kompiliatoriaus kontekste, todėl nustatyta jų išlaikymo politika ŠALTINIS
.