Vodič za uslužne programe Reflection u Guavi
1. Pregled
U ovom ćemo članku pogledati Guavaodraz API - koji je definitivno svestraniji u usporedbi sa standardnim Java refleksivnim API-jem.
Koristit ćemo Guava za hvatanje generičkih tipova tijekom izvođenja i dobro ćemo ih iskoristiti Nepozvan također.
2. Snimanje generičkog tipa tijekom izvođenja
U Javi se generički provodi s brisanjem tipova. To znači da su informacije o generičkom tipu dostupne samo u vrijeme sastavljanja, a za vrijeme izvođenja više nisu dostupne.
Na primjer, Popis, informacije o generičkom tipu brišu se tijekom izvođenja. Zbog te činjenice nije sigurno prenijeti generički Razred objekti u vrijeme izvođenja.
Na kraju bismo mogli dodijeliti dva popisa koji imaju različite generičke tipove istoj referenci, što očito nije dobra ideja:
Popis stringList = Lists.newArrayList (); Popis intList = Lists.newArrayList (); boolean rezultat = stringList.getClass () .isAssignableFrom (intList.getClass ()); assertTrue (rezultat);
Zbog brisanja tipa, metoda isAssignableFrom () ne mogu znati stvarni generički tip popisa. U osnovi uspoređuje dvije vrste koje su samo a Popis bez ikakvih podataka o stvarnom tipu.
Korištenjem standardnog Java refleksivnog API-ja možemo otkriti generičke tipove metoda i klasa. Ako imamo metodu koja vraća a Popis, pomoću refleksije možemo dobiti povratnu vrstu te metode - a ParameterizedType zastupajući Popis.
The TypeToken klasa koristi ovo rješenje kako bi omogućila manipulaciju generičkim tipovima. Možemo koristiti TypeToken klase za hvatanje stvarne vrste generičkog popisa i provjeru mogu li se na njih zaista uputiti istom referencom:
TypeToken stringListToken = novi TypeToken() {}; TypeToken integerListToken = novi TypeToken() {}; TypeToken numberTypeToken = novi TypeToken() {}; assertFalse (stringListToken.isSubtypeOf (integerListToken)); assertFalse (numberTypeToken.isSubtypeOf (integerListToken)); assertTrue (integerListToken.isSubtypeOf (numberTypeToken));
Samo integerListToken može se dodijeliti referenci tipa nubmerTypeToken jer an Cijeli broj razred produžuje a Broj razred.
3. Snimanje složenih vrsta pomoću TypeToken
Recimo da želimo stvoriti generičku parametriziranu klasu i želimo imati informacije o generičkom tipu tijekom izvođenja. Možemo stvoriti razred koji ima TypeToken kao polje za hvatanje tih podataka:
apstraktna klasa ParametrizedClass {TypeToken type = new TypeToken (getClass ()) {}; }
Tada će, prilikom stvaranja instance te klase, generički tip biti dostupan za vrijeme izvođenja:
ParametrizedClass parametrizedClass = novi ParametrizedClass () {}; assertEquals (parametrizedClass.type, TypeToken.of (String.class));
Također možemo stvoriti i TypeToken složenog tipa koji ima više od jednog generičkog tipa i dohvaćaju informacije o svakom od tih tipova tijekom izvođenja:
TypeToken funToken = novi TypeToken() {}; TypeToken funResultToken = funToken .resolveType (Function.class.getTypeParameters () [1]); assertEquals (funResultToken, TypeToken.of (String.class));
Dobivamo stvarni tip povrata za Funkcija, to je Niz. Na karti možemo dobiti čak i vrstu unosa:
TypeToken
Ovdje se služimo metodom refleksije getMethod () iz standardne biblioteke Java za hvatanje tipa povratka metode.
4. Nepozvan
The Nepozvan je tečni omot od java.lang.reflect.Method i java.lang.reflect.Constructor. Pruža jednostavniji API povrh standardne Jave odraz API. Recimo da imamo razred koji ima dvije javne metode i jedna od njih je konačna:
klasa CustomClass {public void somePublicMethod () {} public final void notOverridablePublicMethod () {}}
Sada ispitajmo somePublicMethod () koristeći Guava API i Java standard odraz API:
Metoda metode = CustomClass.class.getMethod ("somePublicMethod"); Nepozivljiv dozivan = novi TypeToken () {} .metoda (metoda); logička isPublicStandradJava = Modifikator.isPublic (method.getModifiers ()); logička isPublicGuava = invokable.isPublic (); assertTrue (isPublicStandradJava); assertTrue (isPublicGuava);
Između ove dvije varijante nema velike razlike, ali provjera je li metoda nadrediva uistinu je ne trivijalan zadatak u Javi. Srećom, isOverridable () metoda iz Nepozvan klasa olakšava:
Metoda metode = CustomClass.class.getMethod ("notOverridablePublicMethod"); Nepozivljiv dozivan = novi TypeToken () {} .metoda (metoda); 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);
Vidimo da čak i za tako jednostavnu operaciju treba puno provjera koristeći standard odraz API. The Nepozvan class to skriva iza API-ja koji je jednostavan za upotrebu i vrlo sažet.
5. Zaključak
U ovom smo članku gledali API za odraz Guave i usporedili ga sa standardnom Javom. Vidjeli smo kako hvatanje generičkih tipova tijekom izvođenja i kako Nepozvan klasa pruža elegantan i jednostavan API za kôd koji koristi refleksiju.
Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.