Programování

Jak popsat kód Java s anotacemi

Pravděpodobně jste se setkali se situacemi, kdy je potřeba se spojit metadata (data, která popisují další data) s třídami, metodami a / nebo jinými aplikačními prvky. Například váš programovací tým možná bude muset identifikovat nedokončené třídy ve velké aplikaci. U každé nedokončené třídy by metadata pravděpodobně obsahovala jméno vývojáře odpovědného za dokončení třídy a očekávané datum dokončení třídy.

Před Java 5 byly komentáře jediným flexibilním mechanismem, který Java musela nabídnout pro přidružení metadat k prvkům aplikace. Komentáře jsou však špatná volba. Protože je kompilátor ignoruje, komentáře nejsou za běhu k dispozici. A i kdyby byly k dispozici, musel by se text analyzovat, aby se získaly důležité datové položky. Bez standardizace způsobu zadávání datových položek by tyto datové položky mohly být analyzovány jako nemožné.

stáhnout Získat kód Stáhněte si zdrojový kód pro příklady v tomto výukovém programu Java 101. Vytvořil Jeff Friesen pro.

Nestandardní anotační mechanismy

Java poskytuje nestandardní mechanismy pro přidružení metadat k prvkům aplikace. Například přechodný vyhrazené slovo vám umožní opatřit poznámkami (přidružit data k) polím, která mají být během serializace vyloučena.

Java 5 zavedením vše změnila anotace, standardní mechanismus pro přidružení metadat k různým prvkům aplikace. Tento mechanismus se skládá ze čtyř komponent:

  • An @rozhraní mechanismus pro deklarování typů anotací.
  • Typy metaznaček, které můžete použít k identifikaci prvků aplikace, na které se vztahuje typ anotace; identifikovat životnost anotace (instance typu anotace); a více.
  • Podpora zpracování anotací prostřednictvím rozšíření rozhraní Java Reflection API (bude popsáno v budoucím článku), které můžete použít k objevení běhových anotací programu a zobecněný nástroj pro zpracování anotací.
  • Standardní typy anotací.

Jak procházíme tímto článkem, vysvětlím, jak tyto komponenty používat.

Deklarace typů anotací pomocí @interface

Typ anotace můžete deklarovat zadáním @ symbol bezprostředně následovaný symbolem rozhraní vyhrazené slovo a identifikátor. Například výpis 1 deklaruje jednoduchý typ anotace, který můžete použít k anotaci kódu bezpečného pro vlákna.

Výpis 1:ThreadSafe.java

public @interface ThreadSafe {}

Po deklaraci tohoto typu anotace předpřipravte před metody, které považujete za bezpečné pro vlákna, instance tohoto typu @ bezprostředně následuje název typu do záhlaví metody. Výpis 2 nabízí jednoduchý příklad, kdy hlavní() metoda je anotována @ThreadSafe.

Výpis 2:AnnDemo.java (verze 1)

veřejná třída AnnDemo {@ThreadSafe public static void main (String [] args) {}}

ThreadSafe instance neposkytují žádná metadata kromě názvu typu poznámky. Můžete však zadat metadata přidáním prvků k tomuto typu, kde živel je hlavička metody umístěná v těle typu anotace.

Kromě toho, že nemají těla kódu, podléhají prvky následujícím omezením:

  • Záhlaví metody nemůže deklarovat parametry.
  • Záhlaví metody nemůže poskytnout klauzuli throws.
  • Návratový typ hlavičky metody musí být primitivní typ (např. int), řetězec java.lang, java.lang.Class, výčet, typ anotace nebo pole jednoho z těchto typů. Pro návratový typ nelze zadat žádný jiný typ.

Jako další příklad uvádí výpis 3 a Dělat typ poznámky se třemi prvky, které identifikují konkrétní úlohu kódování, určují datum, kdy má být úloha dokončena, a pojmenují kodéra odpovědného za dokončení úlohy.

Výpis 3:ToDo.java (verze 1)

public @interface ToDo {int id (); Řetězec finishDate (); String coder () výchozí "n / a"; }

Všimněte si, že každý prvek nedeklaruje žádné parametry nebo vrhá klauzuli, má legální návratový typ (int nebo Tětiva) a končí středníkem. Konečný prvek také odhaluje, že lze zadat výchozí návratovou hodnotu; tato hodnota je vrácena, pokud anotace nepřiřadí prvku hodnotu.

Výpis 4 použití Dělat anotovat nedokončenou metodu třídy.

Výpis 4:AnnDemo.java (verze 2)

public class AnnDemo {public static void main (String [] args) {String [] cities = {"New York", "Melbourne", "Peking", "Moskva", "Paříž", "Londýn"}; druh (města); } @ToDo (id = 1000, finishDate = "10.10.2019", coder = "John Doe") statické zrušení neplatnosti (objekty [] objekty) {}}

Výpis 4 přiřadí každému prvku položku metadat; například, 1000 je přiřazen id. Na rozdíl od kodérid a dokončitDatum prvky musí být specifikovány; jinak kompilátor nahlásí chybu. Když kodér není přiřazena hodnota, předpokládá se její výchozí hodnota „n / a“ hodnota.

Java poskytuje speciální Řetězcová hodnota () prvek, který lze použít k vrácení seznamu položek metadat oddělených čárkami. Výpis 5 ukazuje tento prvek v refaktorované verzi Dělat.

Výpis 5:ToDo.java (verze 2)

public @interface ToDo {String value (); }

Když hodnota() je jediný prvek typu anotace, nemusíte specifikovat hodnota a = operátor přiřazení při přiřazení řetězce k tomuto prvku. Výpis 6 ukazuje oba přístupy.

Výpis 6:AnnDemo.java (verze 3)

public class AnnDemo {public static void main (String [] args) {String [] cities = {"New York", "Melbourne", "Peking", "Moskva", "Paříž", "Londýn"}; druh (města); } @ToDo (value = "1000,10 / 10/2019, John Doe") statické void řazení (Object [] objekty) {} @ToDo ("1000,10 / 10/2019, John Doe") statické booleovské vyhledávání ( Object [] objects, Object key) {return false; }}

Použití typů metaanotací - problém flexibility

Můžete anotovat typy (např. Třídy), metody, lokální proměnné a další. Tato flexibilita však může být problematická. Možná budete chtít například omezit Dělat pouze na metody, ale nic nebrání tomu, aby byl použit k anotaci dalších prvků aplikace, jak je ukázáno v seznamu 7.

Výpis 7:AnnDemo.java (verze 4)

@ToDo ("1000,10 / 10/2019, John Doe") veřejná třída AnnDemo {public static void main (String [] args) {@ToDo (value = "1000,10 / 10/2019, John Doe") String [] města = {"New York", "Melbourne", "Peking", "Moskva", "Paříž", "Londýn"}; druh (města); } @ToDo (value = "1000,10 / 10/2019, John Doe") statické void řazení (Object [] objekty) {} @ToDo ("1000,10 / 10/2019, John Doe") statické booleovské vyhledávání ( Object [] objects, Object key) {return false; }}

V seznamu 7, Dělat se také používá k anotaci souboru AnnDemo třída a města lokální proměnná. Přítomnost těchto chybných anotací může někoho zmást při kontrole vašeho kódu nebo dokonce vašich vlastních nástrojů pro zpracování anotací. Pro časy, kdy potřebujete zúžit flexibilitu typu anotace, nabízí Java cílová anotační typ v jeho poznámka java.lang balík.

cílová je meta-anotační typ - typ anotace, jehož anotace anotuje anotační typy, na rozdíl od nemetanotického typu, jehož anotace anotují aplikační prvky, jako jsou třídy a metody. Identifikuje druhy prvků aplikace, pro které je použit typ anotace. Tyto prvky jsou označeny cílováJe Hodnota ElementValue [] () živel.

java.lang.annotation.ElementType je výčet, jehož konstanty popisují aplikační prvky. Například, KONSTRUKTOR platí pro konstruktory a PARAMETR platí pro parametry. Seznam 8 refaktorů Seznam 5 Dělat typ poznámky omezit pouze na metody.

Výpis 8:ToDo.java (verze 3)

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

Vzhledem k refaktorování Dělat typ poznámky, pokus o kompilaci Výpisu 7 má nyní za následek následující chybovou zprávu:

AnnDemo.java:1: error: annotation type not applicable to this kind of declaration @ToDo ("1000,10 / 10/2019, John Doe") ^ AnnDemo.java:6: error: annotation type not applicable to this kind of Declaration @ToDo (value = "1000,10 / 10/2019, John Doe") ^ 2 errors

Další typy metaanotací

Java 5 představila tři další typy metaanotací, které se nacházejí v poznámka java.lang balík:

  • Zadržení označuje, jak dlouho mají být zachovány anotace s anotovaným typem. Tento typ je přidružen java.lang.annotation.RetentionPolicy enum deklaruje konstanty TŘÍDA (kompilátor zaznamenává anotace do souboru třídy; virtuální stroj je neuchovává, aby šetřil paměť - výchozí zásada), RUNTIME (kompilátor zaznamenává anotace do souboru třídy; virtuální stroj je uchovává) a ZDROJ (kompilátor zahodí anotace).
  • Zdokumentováno označuje, že instance Zdokumentováno-anotované anotace mají být dokumentovány javadoc a podobné nástroje.
  • Zděděno označuje, že typ anotace je automaticky zděděn.

Java 8 představila java.lang.annotation.Repeatable meta-anotační typ. Opakovatelný se používá k označení, že typ anotace, jejíž deklaraci anotuje (meta-), je opakovatelný. Jinými slovy můžete na prvek aplikace použít více anotací ze stejného opakovatelného typu anotace, jak je ukázáno zde:

@ToDo (hodnota = "1000,10 / 10/2019, John Doe") @ToDo (hodnota = "1001,10 / 10/2019, Kate Doe") statické třídění void (Object [] objekty) {}

Tento příklad to předpokládá Dělat byl anotován s Opakovatelný typ poznámky.

Zpracování anotací

Anotace jsou určeny ke zpracování; jinak je nemá smysl mít. Java 5 rozšířila rozhraní Reflection API, aby vám pomohla vytvořit vlastní nástroje pro zpracování anotací. Například, Třída prohlašuje Anotace [] getAnnotations () metoda, která vrací pole java.lang.Annotation instance popisující anotace přítomné na prvku popsaném v Třída objekt.

Výpis 9 představuje jednoduchou aplikaci, která načte soubor třídy a prozkoumá jeho metody Dělat anotace a na výstupu komponenty každé nalezené anotace.

Výpis 9:AnnProcDemo.java

import java.lang.reflect.Method; public class AnnProcDemo {public static void main (String [] args) throws Exception {if (args.length! = 1) {System.err.println ("usage: java AnnProcDemo classfile"); vrátit se; } Metoda [] metody = Class.forName (args [0]). GetMethods (); for (int i = 0; i <methods.length; i ++) {if (methods [i] .isAnnotationPresent (ToDo.class)) {ToDo todo = methods [i] .getAnnotation (ToDo.class); Řetězec [] komponenty = todo.value (). Split (","); System.out.printf ("ID =% s% n", komponenty [0]); System.out.printf ("Datum dokončení =% s% n", komponenty [1]); System.out.printf ("Coder =% s% n% n", komponenty [2]); }}}}

Po ověření, že byl zadán přesně jeden argument příkazového řádku (identifikace souboru třídy), hlavní() načte soubor třídy pomocí Class.forName (), vyvolá getMethods () vrátit pole java.lang.reflect.Method objekty identifikující všechny veřejnost metody v souboru třídy a tyto metody zpracovává.

Zpracování metody začíná vyvoláním MetodaJe boolean isAnnotationPresent (Class annotationClass) metoda k určení, zda anotace popsaná ToDo.class je na metodě přítomen. Pokud ano, MetodaJe T getAnnotation (Class annotationClass) metoda je volána k získání anotace.

The Dělat zpracovávané anotace jsou ty, jejichž typy deklarují jeden Řetězcová hodnota () prvek (viz Výpis 5). Protože metadata založená na řetězcích tohoto prvku jsou oddělena čárkami, je třeba je rozdělit do řady hodnot komponent. Každá ze tří hodnot komponent je poté zpřístupněna a odeslána.

Zkompilovat tento zdrojový kód (javac AnnProcDemo.java). Před spuštěním aplikace budete potřebovat vhodný soubor třídy s @Dělat anotace k jeho veřejnost metody. Můžete například upravit seznam 6 AnnDemo zdrojový kód k zahrnutí veřejnost v jeho sort () a Vyhledávání() záhlaví metody. Budete také potřebovat seznam 10 Dělat typ poznámky, který vyžaduje RUNTIME retenční politika.

Výpis 10:ToDo.java (verze 4)

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

Zkompilovat upravené AnnDemo.java a Výpis 10 a proveďte následující příkaz ke zpracování AnnDemoJe Dělat anotace:

java AnnProcDemo AnnDemo

Pokud vše půjde dobře, měli byste dodržovat následující výstup:

ID = 1000 Datum dokončení = 10/10/2019 Coder = John Doe ID = 1000 Datum dokončení = 10/10/2019 Coder = John Doe

Zpracování anotací pomocí apt a kompilátoru Java

Java 5 představil výstižný nástroj pro všeobecné zpracování anotací. Migrace prostředí Java 6 výstižnýFunkčnost do své javac nástroj kompilátoru a prostředí Java 7 je zastaralé výstižný, který byl následně odstraněn (počínaje Java 8).

Standardní typy anotací

Spolu s cílová, Zadržení, Zdokumentováno, a ZděděnoByla představena Java 5 java.lang. zastaralé, java.lang.Override, a java.lang.SuppressWarnings. Tyto tři typy anotací jsou navrženy pro použití pouze v kontextu kompilátoru, a proto jsou jejich zásady uchovávání nastaveny na ZDROJ.

Zastaralé

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