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 mapToken = nový TypeToken() {}; TypeToken entrySetToken = mapToken .resolveType (Map.class.getMethod ("entrySet") .getGenericReturnType ()); assertEquals (entrySetToken, nový 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.


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