Sprievodca reflexnými nástrojmi spoločnosti Guava
1. Prehľad
V tomto článku sa pozrieme na Guavaodraz API - čo je rozhodne univerzálnejšie v porovnaní so štandardným Java reflect API.
Budeme používať Guava na zachytenie generických typov za behu a my to dobre využijeme Invokable tiež.
2. Zachytenie generického typu za behu
V Jave sú generické typy implementované s vymazaním typu. To znamená, že informácie o všeobecnom type sú k dispozícii iba v čase kompilácie a za behu programu - už nie sú k dispozícii.
Napríklad, Zoznam, informácie o generickom type sa za behu vymažú. Z tohto dôvodu nie je bezpečné obchádzať druhové lieky Trieda objekty za behu.
Mohli by sme nakoniec priradiť dva zoznamy, ktoré majú rôzne generické typy, k rovnakému odkazu, čo zjavne nie je dobrý nápad:
List stringList = Lists.newArrayList (); Zoznam intList = Lists.newArrayList (); boolovský výsledok = stringList.getClass () .isAssignableFrom (intList.getClass ()); assertTrue (výsledok);
Z dôvodu vymazania typu je to metóda isAssignableFrom () nemôže poznať skutočný všeobecný typ zoznamov. V zásade porovnáva dva typy, ktoré sú len a Zoznam bez akýchkoľvek informácií o skutočnom type.
Pomocou štandardného odrazového rozhrania Java môžeme zistiť všeobecné typy metód a tried. Ak máme metódu, ktorá vracia a Zoznam, môžeme použiť odraz na získanie návratového typu tejto metódy - a ParameterizedType zastupujúci Zoznam.
The TypeToken trieda používa toto riešenie na umožnenie manipulácie s generickými typmi. Môžeme použiť TypeToken triedy, aby zachytili skutočný typ generického zoznamu a skontrolovali, či na ne skutočne možno odkazovať rovnakým odkazom:
TypeToken stringListToken = nový TypeToken() {}; TypeToken integerListToken = nový TypeToken() {}; TypeToken numberTypeToken = nový TypeToken() {}; assertFalse (stringListToken.isSubtypeOf (integerListToken)); assertFalse (numberTypeToken.isSubtypeOf (integerListToken)); assertTrue (integerListToken.isSubtypeOf (numberTypeToken));
Len integerListToken možno priradiť k referencii typu nubmerTypeToken pretože an Celé číslo trieda rozširuje a Číslo trieda.
3. Zachytenie zložitých typov pomocou TypeToken
Povedzme, že chceme vytvoriť všeobecnú parametrizovanú triedu a chceme mať informácie o všeobecnom type za behu. Môžeme vytvoriť triedu, ktorá má TypeToken ako pole na zachytenie týchto informácií:
abstraktná trieda ParametrizedClass {TypeToken typ = nový TypeToken (getClass ()) {}; }
Potom pri vytváraní inštancie tejto triedy bude generický typ k dispozícii za behu:
ParametrizedClass parametrizedClass = new ParametrizedClass () {}; assertEquals (parametrizedClass.type, TypeToken.of (String.class));
Môžeme tiež vytvoriť a TypeToken komplexného typu, ktorý má viac ako jeden všeobecný typ, a za behu načítať informácie o každom z týchto typov:
TypeToken funToken = nový TypeToken() {}; TypeToken funResultToken = funToken .resolveType (Function.class.getTypeParameters () [1]); assertEquals (funResultToken, TypeToken.of (String.class));
Získame skutočný typ návratu pre Funkcia, toto je String. Na mape môžeme dokonca nájsť typ záznamu:
TypeToken
Tu používame reflexnú metódu getMethod () zo štandardnej knižnice Java na zachytenie návratového typu metódy.
4. Invokable
The Invokable je plynulý obal z java.lang.reflect.Metóda a java.lang.reflect.Constructor. Poskytuje jednoduchšie API okrem štandardnej Javy odraz API. Povedzme, že máme triedu, ktorá má dve verejné metódy a jedna z nich je konečná:
trieda CustomClass {public void somePublicMethod () {} verejné posledné void notOverridablePublicMethod () {}}
Teraz poďme preskúmať somePublicMethod () pomocou štandardu Guava API a Java odraz API:
Metóda method = CustomClass.class.getMethod ("somePublicMethod"); Invokable invokable = new TypeToken () {} .method (method); boolean isPublicStandradJava = Modifier.isPublic (method.getModifiers ()); boolean isPublicGuava = invokable.isPublic (); assertTrue (isPublicStandradJava); assertTrue (isPublicGuava);
Medzi týmito dvoma variantmi nie je veľký rozdiel, ale kontrola, či je nejaká metóda prepísateľná, je v Jave skutočne netriviálna úloha. Našťastie isOverridable () metóda z Invokable trieda to uľahčuje:
Metóda method = CustomClass.class.getMethod ("notOverridablePublicMethod"); Invokable invokable = new TypeToken () {} .method (method); boolean isOverridableStandardJava = (! (Modifier.isFinal (method.getModifiers ()) || Modifier.isPrivate (method.getModifiers ()) || Modifier.isStatic (method.getModifiers ()) || Modifier.isFinal (method.getDeclaringClass ( ) .getModifiers ()))); boolean isOverridableFinalGauava = invokable.isOverridable (); assertFalse (isOverridableStandardJava); assertFalse (isOverridableFinalGauava);
Vidíme, že aj takáto jednoduchá operácia vyžaduje veľa kontrol pomocou štandardu odraz API. The Invokable class to skrýva za API, ktoré sa ľahko používa a je veľmi stručné.
5. Záver
V tomto článku sme sa pozreli na Guava reflexné API a porovnali ho so štandardnou Javou. Videli sme, ako zachytiť generické typy za behu a ako Invokable trieda poskytuje elegantné a ľahko použiteľné API pre kód využívajúci reflexiu.
Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub - jedná sa o projekt Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.