Útmutató a Java reflexióhoz

1. Áttekintés

Ebben a cikkben a Java tükrözését fogjuk vizsgálni, amely lehetővé teszi számunkra az osztályok, interfészek, mezők és módszerek futásidejű attribútumainak vizsgálatát vagy módosítását. Ez különösen jól jön, ha fordításkor nem ismerjük a nevüket.

Emellett példányosíthatunk új objektumokat, meghívhatunk módszereket, és lekérdezhetjük vagy beállíthatjuk a mezőértékeket a reflexió segítségével.

2. Projekt beállítása

A Java reflexió használatához nincs szükségünk speciális edényekre, bármilyen speciális konfiguráció vagy Maven-függőség. A JDK olyan osztályok csoportjával szállít, amelyek a java.lang.reflect csomagot kifejezetten erre a célra.

Tehát csak annyit kell tennünk, hogy a következő importálást hajtjuk végre kódunkba:

import java.lang.reflect. *;

és jól megyünk.

Ahhoz, hogy hozzáférhessünk egy példány osztályához, módszeréhez és terepi információihoz, az úgynevezett getClass metódus, amely visszaadja az objektum futásidejű osztályábrázolását. A visszatért osztály Az object módszereket kínál az osztály információinak elérésére.

3. Egyszerű példa

Ahhoz, hogy nedves legyen a lábunk, megnézünk egy nagyon egyszerű példát, amely futás közben ellenőrzi egy egyszerű Java objektum mezőit.

Hozzunk létre egy egyszerű Személy osztály csak név és kor mezők és egyáltalán nincsenek módszerek. Itt van a Személy osztály:

public class Személy {private String név; privát int kor; }

Most a Java reflexióval fogjuk felfedezni az osztály összes mezőjének nevét. A reflexió erejének értékelése érdekében elkészítjük a Személy objektumot, és használja az Object hivatkozási típusként:

@Test public void givenObject_whenGetsFieldNamesAtRuntime_thenCorrect () {Object person = new Person (); Field [] mezők = person.getClass (). GetDeclaredFields (); List actualFieldNames = getFieldNames (mezők); assertTrue (Tömbök.asList ("név", "kor") .containsAll (ténylegesMezőNév)); }

Ez a teszt megmutatja, hogy képesek vagyunk egy tömb megszerzésére Field tárgyak a mi személy objektumra, még akkor is, ha az objektumra való hivatkozás az adott objektum szülőtípusa.

A fenti példában csak ezeknek a mezőknek a neve érdekelt minket, de ennél sokkal többet lehet tenni, és további példákat látunk erre a következő szakaszokban.

Figyelje meg, hogyan használunk segítő módszert a tényleges mezőnevek kinyerésére, ez egy nagyon egyszerű kód:

privát statikus lista getFieldNames (mező [] mezők) {lista mezőnevek = új tömblista (); for (Mező mező: mezők) mezőNév.add (mező.címNév ()); return fieldNames; }

4. Java Reflection használati esetek

Mielőtt rátérnénk a Java reflexió különféle jellemzőire, megvitatunk néhány általános felhasználási lehetőséget, amelyeket erre találhatunk. A Java reflexió rendkívül hatékony, és számos szempontból nagyon hasznos lehet.

Például sok esetben van elnevezési megállapodásunk az adatbázis-táblákhoz. Dönthetünk úgy, hogy hozzáadjuk a konzisztenciát azáltal, hogy előre rögzítjük a táblázatainkat tbl_, oly módon, hogy hallgatói adatokkal ellátott táblázatot hívunk meg tbl_student_data.

Ilyen esetekben a hallgatói adatokat tároló Java objektumot nevezhetjük Diák vagy StudentData. Ezután a CRUD paradigmát használva minden művelethez van egy belépési pontunk Teremt műveletek csak egy Tárgy paraméter.

Ezután a reflexió segítségével lekérjük az objektum nevét és a mezőneveket. Ezen a ponton leképezhetjük ezeket az adatokat egy DB táblába, és az objektum mező értékeit hozzárendelhetjük a megfelelő DB mező nevekhez.

5. Java osztályok ellenőrzése

Ebben a részben a Java Reflection API legalapvetőbb összetevőjét fogjuk megvizsgálni. A Java osztályú objektumok, amint azt korábban említettük, hozzáférést biztosítanak minden objektum belső részleteihez.

Megvizsgáljuk a belső részleteket, például egy objektum osztálynevét, módosítókat, mezőket, módszereket, megvalósított interfészeket stb.

5.1. Készülődni

Annak érdekében, hogy szilárdan megismerhessük a reflektálás API-t, ahogyan azt a Java osztályokra alkalmazzuk, és sokféle példával rendelkezünk, létrehozunk egy absztraktot Állat osztály, amely végrehajtja a Enni felület. Ez a felület meghatározza a beton étkezési viselkedését Állat az általunk létrehozott objektum.

Tehát először is itt van a Enni felület:

nyilvános felület Eating {String eszik (); }

majd a beton Állat a Enni felület:

public absztrakt osztály Állateszközök Eating {public static String CATEGORY = "házi"; privát karakterlánc neve; védett absztrakt karakterlánc getSound (); // kivitelező, szabványos mérőeszközök és beállítók kihagyva}

Hozzunk létre egy másik felületet is Mozgás amely leírja az állat mozgását:

nyilvános felület Locomotion {String getLocomotion (); }

Most létrehozunk egy konkrét osztályt Kecske amely kiterjed Állat és megvalósítja Mozgás. Mivel a szuperosztály megvalósítja Enni, Kecske az interfész módszereit is végre kell hajtania:

public class Kecske kiterjeszti az állati eszközöket Locomotion {@Orride protected String getSound () {return "bleat"; } @Orride public String getLocomotion () {return "sétál"; } @Orride public String eszik () {return "fű"; } // kivitelező kihagyva}

Ettől a ponttól kezdve a Java tükröződést használjuk a Java osztályok fenti osztályokban és felületeken megjelenő aspektusainak ellenőrzésére.

5.2. Osztálynevek

Kezdjük azzal, hogy egy objektum nevét megkapjuk a Osztály:

@Test public void givenObject_whenGetsClassName_thenCorrect () {Object goat = new Goat ("kecske"); Class clazz = goat.getClass (); assertEquals ("Kecske", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Kecske", clazz.getName ()); assertEquals ("com.baeldung.reflection.Kecske", clazz.getCanonicalName ()); }

Vegye figyelembe, hogy a getSimpleName a metódusa Osztály az objektum alapnevét adja vissza, amint az a deklarációban megjelenik. Ezután a másik két módszer visszaadja a teljesen minősített osztálynevet, beleértve a csomag deklarációt is.

Lássuk azt is, hogyan hozhatunk létre egy objektumot a Kecske osztály, ha csak annak teljesen minősített osztálynevét ismerjük:

@Test public void givenClassName_whenCreatesObject_thenCorrect () {Class clazz = Class.forName ("com.baeldung.reflection.Goat"); assertEquals ("Kecske", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Kecske", clazz.getName ()); assertEquals ("com.baeldung.reflection.Kecske", clazz.getCanonicalName ()); }

Figyeljük meg, hogy a név, amelyet átadunk a statikusnak forName metódusnak tartalmaznia kell a csomag adatait. Ellenkező esetben a ClassNotFoundException.

5.3. Osztálymódosítók

Meghatározhatjuk az osztályban használt módosítókat a getModifiers metódus, amely egy Egész szám. Minden módosító egy jelző bit, amely vagy be van állítva, vagy törölve van.

A java.lang.reflect.Modifier osztály statikus módszereket kínál, amelyek elemzik a visszaküldötteket Egész szám egy adott módosító jelenlétére vagy hiányára.

Erősítsük meg a fent definiált osztályok néhány módosítóját:

@Test public void givenClass_whenRecognisesModifiers_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); int goatMods = goatClass.getModifiers (); int animalMods = animalClass.getModifiers (); assertTrue (Módosító.isPublic (goatMods)); assertTrue (Módosító.isAbsztrakt (animalMods)); assertTrue (Módosító.isPublic (animalMods)); }

Bármely osztály módosítóját ellenőrizhetjük egy könyvtárban, amelyet a projektünkbe importálunk.

A legtöbb esetben szükség lehet a forName megközelítés helyett a teljes körű példányosítás, mivel ez drága eljárás lenne a memória nehéz osztályai esetében.

5.4. Csomag információk

A Java reflektálás használatával információkat is szerezhetünk bármely osztály vagy objektum csomagjáról. Ezek az adatok a Csomag osztály, amelyre visszahívás érkezik getPackage metódus az osztály objektumon.

Futtassunk egy tesztet a csomag nevének lekérésére:

@Test public void givenClass_whenGetsPackageInfo_thenCorrect () {Kecske kecske = új Kecske ("kecske"); Osztály goatClass = goat.getClass (); Csomag pkg = goatClass.getPackage (); assertEquals ("com.baeldung.reflection", pkg.getName ()); }

5.5. Szuper osztály

Bármely Java osztály szuperosztályát megszerezhetjük a Java reflektálás használatával is.

Sok esetben, különösen a könyvtári osztályok vagy a Java beépített osztályainak használata során, előfordulhat, hogy előzetesen nem ismerjük az általunk használt objektum szuperosztályát, ez az alfejezet megmutatja, hogyan lehet ezeket az információkat megszerezni.

Tehát menjünk előre, és határozzuk meg a szuperosztályt Kecske. Ezenkívül azt is megmutatjuk java.lang.String osztály az alosztálya java.lang.Tárgy osztály:

@Test public void givenClass_whenGetsSuperClass_thenCorrect () {Kecske kecske = új Kecske ("kecske"); String str = "bármilyen karakterlánc"; Osztály goatClass = goat.getClass (); Osztály goatSuperClass = goatClass.getSuperclass (); assertEquals ("Animal", goatSuperClass.getSimpleName ()); assertEquals ("Objektum", str.getClass (). getSuperclass (). getSimpleName ()); }

5.6. Megvalósított interfészek

A Java reflektálás segítségével mi is képesek vagyunk rá az adott osztály által megvalósított interfészek listájának lekérése.

Keressük meg a. Által megvalósított interfészek osztálytípusait Kecske osztály és a Állat absztrakt osztály:

@Test public void givenClass_whenGetsImplementedInterfaces_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Osztály [] goatInterfaces = goatClass.getInterfaces (); Class [] animalInterfaces = animalClass.getInterfaces (); assertEquals (1, kecskefelületek.hossz); assertEquals (1, állati Interfészek.hossz); assertEquals ("Locomotion", goatInterfaces [0] .getSimpleName ()); assertEquals ("Eating", animalInterfaces [0] .getSimpleName ()); }

Az állításokból vegye figyelembe, hogy minden osztály csak egyetlen interfészt valósít meg. Ezen interfészek nevét megvizsgálva azt találjuk Kecske megvalósítja Mozgás és Állat megvalósítja Enni, ahogy az a kódunkban is megjelenik.

Lehet, hogy ezt megfigyelte Kecske az absztrakt osztály egyik alosztálya Állat és megvalósítja az interfész módszert eszik (), azután, Kecske megvalósítja a Enni felület.

Ezért érdemes megjegyezni, hogy csak azok a csatolók, amelyeket egy osztály kifejezetten deklarál, hogy megvalósultak a megvalósítja kulcsszó jelenik meg a visszatérő tömbben.

Tehát akkor is, ha egy osztály interfész-módszereket valósít meg, mert a szuperosztálya valósítja meg ezt az interfészt, de az alosztály nem közvetlenül deklarálja ezt megvalósítja kulcsszó, akkor az a felület nem jelenik meg az interfészek tömbjében.

5.7. Kivitelezők, módszerek és mezők

A Java reflektálás segítségével képesek vagyunk megvizsgálni bármely objektum osztályának konstruktorait, valamint a módszereket és mezőket.

Később mélyebb vizsgálatokat láthatunk majd az osztály minden egyes összetevőjéről, de egyelőre elegendő csak megkapni a nevüket és összehasonlítani őket azzal, amire számítunk.

Nézzük meg, hogyan lehet megszerezni a Kecske osztály:

@Test public void givenClass_whenGetsConstructor_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Konstruktor [] konstruktorok = goatClass.getConstructors (); assertEquals (1, konstruktorok.hossz); assertEquals ("com.baeldung.reflection.Kecske", konstruktorok [0] .getName ()); }

Megvizsgálhatjuk a Állat osztály, így:

@Test public void givenClass_whenGetsFields_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Field [] mezők = animalClass.getDeclaredFields (); Felsorolja a tényleges mezőket = getFieldNames (mezők); assertEquals (2, actualFields.size ()); assertTrue (actualFields.containsAll (Arrays.asList ("név", "KATEGÓRIA"))); }

Ahogy mi is ellenőrizhetjük a Állat osztály:

@Test public void givenClass_whenGetsMethods_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Method [] módszerek = animalClass.getDeclaredMethods (); Sorolja fel a ténylegesMethods = getMethodNames (módszereket); assertEquals (4, actualMethods.size ()); assertTrue (actualMethods.containsAll (Arrays.asList ("getName", "setName", "getSound"))); }

Mint getFieldNames, felvettünk egy segítő metódust a metódusnevek lekérésére a. tömbből Módszer tárgyak:

privát statikus lista getMethodNames (Method [] metódusok) {List methodNames = új ArrayList (); for (Metódus módszer: módszerek) metódusnevek.add (metódus.neve ()); return methodNames; }

6. A kivitelezők ellenőrzése

Java reflexióval megtehetjük ellenőrizze a kivitelezőket bármely osztályból, sőt osztály objektumokat hozhat létre futás közben. Ezt a java.lang.reflect.Constructor osztály.

Korábban csak azt vizsgáltuk, hogyan lehet megszerezni a tömböt Konstruktőr tárgyak, amelyekből meg tudtuk szerezni a kivitelezők nevét.

Ebben a szakaszban arra fogunk koncentrálni, hogy miként lehet lekérni adott konstruktorokat. A Java-ban, mint tudjuk, egy osztály két konstruktora nem osztja meg pontosan ugyanazt a metódus-aláírást. Tehát ezt az egyediséget arra használjuk, hogy egy kivitelezőt kapjunk a sok közül.

Az osztály jellemzőinek értékelése érdekében létrehozunk egy Madár alosztálya Állat három kivitelezővel. Nem fogjuk végrehajtani Mozgás hogy a konstruktor argumentummal megadhassuk ezt a viselkedést, még több változatosságot adhatunk hozzá:

nyilvános osztályú Bird kiterjeszti az állati {privát logikai sétákat; public Bird () {super ("madár"); } public Bird (karakterlánc neve, logikai séták) {super (név); setWalks (séták); } public Bird (String name) {szuper (név); } nyilvános logikai séta () {visszaút; } // szabványos beállítók és felülbírált módszerek}

A reflexió segítségével erősítsük meg, hogy ennek az osztálynak három konstruktora van:

@Test public void givenClass_whenGetsAllConstructors_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Konstruktor [] konstruktorok = birdClass.getConstructors (); assertEquals (3, konstruktorok.hossz); }

Ezután minden konstruktort lekérünk a Madár osztály a konstruktor paraméterosztályainak átadásával deklarált sorrendben:

@Test public void givenClass_whenGetsEachConstructorByParamTypes_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Konstruktor cons1 = birdClass.getConstructor (); Konstruktor cons2 = birdClass.getConstructor (String.class); Konstruktor cons3 = birdClass.getConstructor (String.osztály, logikai.osztály); }

Nincs szükség állításra, mivel amikor nem létezik konstruktor az adott sorrendben megadott paramétertípusokkal, akkor kapunk egy NoSuchMethodException és a teszt automatikusan sikertelen lesz.

Az utolsó teszt során megtudjuk, hogyan lehet futás közben példányosítani az objektumokat, miközben megadjuk a paramétereiket:

@Test public void givenClass_whenInstantiatesObjectsAtRuntime_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Konstruktor cons1 = birdClass.getConstructor (); Konstruktor cons2 = birdClass.getConstructor (String.class); Konstruktor cons3 = birdClass.getConstructor (String.osztály, logikai.osztály); Madármadár1 = (Bird) cons1.neInstance (); Madármadár2 = (Madár) cons2.newstance ("Takácsmadár"); Madármadár3 = (Madár) cons3.newstance ("galamb", igaz); assertEquals ("madár", bird1.getName ()); assertEquals ("Takácsmadár", bird2.getName ()); assertEquals ("galamb", bird3.getName ()); assertFalse (madár1.séták ()); assertTrue (madár3.séták ()); }

Az osztály objektumokat példányosítjuk a newInstance a metódusa Konstruktőr osztály és a szükséges paraméterek deklarált sorrendben történő átadása. Ezután az eredményt a kívánt típusra vetjük.

Lehetőség van az alapértelmezett konstruktor meghívására is a Class.newInstance () módszer. Ez a módszer azonban a Java 9 óta elavult, ezért nem szabad ezt használni a modern Java projektekben.

Mert madár1, az alapértelmezett konstruktort használjuk, amely a mi Madár kódot, automatikusan madárra állítja a nevet, és ezt egy teszttel megerősítjük.

Ezután instantizálunk madár2 csak névvel és teszttel is, ne feledje, hogy amikor nem a mozdulati viselkedést állítjuk be alapértelmezés szerint hamisnak, amint az az utolsó két állításban látható.

7. Mezők ellenőrzése

Korábban csak a mezők nevét vizsgáltuk meg, ebben a szakaszban, megmutatjuk, hogyan kellfutás közben kapják meg és állítsák be értékeiket.

Két fő módszer használható az osztályok mezőinek futás közbeni ellenőrzésére: getFields () és getField (fieldName).

A getFields () metódus a kérdéses osztály összes elérhető nyilvános mezőjét adja eredményül. Visszaadja az összes nyilvános mezőt mind az osztályban, mind az összes szuperosztályban.

Például, amikor ezt a módszert hívjuk a Madár osztályban, csak a KATEGÓRIA szuperosztályának területe, Állat, mivel Madár maga nem deklarál nyilvános mezőket:

@Test public void givenClass_whenGetsPublicFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Field [] mezők = birdClass.getFields (); assertEquals (1, mezők.hossz); assertEquals ("CATEGORY", mezők [0] .getName ()); }

Ennek a módszernek van egy úgynevezett változata is getField amely csak egyet ad vissza Terület objektumot a mező nevének felvételével:

@Test public void givenClass_whenGetsPublicFieldByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Mezőmező = birdClass.getField ("CATEGORY"); assertEquals ("CATEGORY", mező.getName ()); }

Nem férünk hozzá a szuperosztályokban bejelentett és a gyermekosztályban nem bejelentett privát mezőkhöz. Ezért nem tudunk hozzáférni a név terület.

Megvizsgálhatjuk azonban az általunk érintett osztályban bejelentett magánterületeket a getDeclaredFields módszer:

@Test public void givenClass_whenGetsDeclaredFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Field [] mezők = birdClass.getDeclaredFields (); assertEquals (1, mezők.hossz); assertEquals ("séták", mezők [0] .getName ()); }

Használhatjuk annak másik változatát is, ha ismerjük a mező nevét:

@Test public void givenClass_whenGetsFieldsByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Mezőmező = birdClass.getDeclaredField ("sétál"); assertEquals ("séták", field.getName ()); }

Ha rosszul kapjuk meg a mező nevét, vagy beírunk egy nem létező mezőbe, akkor a NoSuchFieldException.

A mezőt a következőképpen kapjuk meg:

@Test public void givenClassField_whenGetsType_thenCorrect () {Field field = Class.forName ("com.baeldung.reflection.Bird") .getDeclaredField ("sétál"); Osztály fieldClass = field.getType (); assertEquals ("logikai érték", fieldClass.getSimpleName ()); }

Ezután megvizsgáljuk, hogyan lehet elérni és módosítani a mezőértékeket. Ahhoz, hogy megkapjuk a mező értékét, nem is a beállításáról, először hívással kell beállítanunk, hogy elérhető legyen setAccessible módszer a Terület objektum és logikai átadása igaz hozzá:

@Test public void givenClassField_whenSetsAndGetsValue_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Madármadár = (Madár) birdClass.getConstructor (). NewInstance (); Mezőmező = birdClass.getDeclaredField ("sétál"); field.setAccessible (true); assertFalse (mező.getBoolean (madár)); assertFalse (madár.sétálások ()); field.set (madár, igaz); assertTrue (mező.getBoolean (madár)); assertTrue (madár.séták ()); }

A fenti tesztben megállapítjuk, hogy valóban a sétál mező hamis, mielőtt igazra állítanánk.

Figyeljük meg, hogyan használjuk a Terület objektum az értékek beállításához és megszerzéséhez azáltal, hogy átadjuk annak az osztálynak a példáját, amellyel foglalkozunk, és esetleg azt az új értéket, amelyet a mezőnek meg kell adnia az objektumban.

Egy fontos dolog, amit meg kell jegyezni Terület objektum az, hogy amikor azt deklarálják nyilvános statikus, akkor nincs szükségünk az osztályt tartalmazó példányra, csak átadhatjuk nulla helyére, és továbbra is megkapja a mező alapértelmezett értékét, így:

@Test public void givenClassField_whenGetsAndSetsWithNull_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Mezőmező = birdClass.getField ("CATEGORY"); field.setAccessible (true); assertEquals ("belföldi", field.get (null)); }

8. Ellenőrzési módszerek

Egy korábbi példában a reflexiót csak a módszernevek ellenőrzésére használtuk. A Java reflexió azonban ennél erősebb.

Java reflexióval megtehetjük metódusokat meghívni a futási idő és átadják nekik a szükséges paramétereket, akárcsak a kivitelezőknél. Hasonlóképpen túlterhelt módszereket is meghívhatunk azáltal, hogy megadjuk az egyes paramétertípusokat.

A mezőkhöz hasonlóan két fő módszert alkalmazunk az osztály metódusainak lekérésére. A getMethods A method az osztály és a szuperosztályok összes nyilvános módszerének tömbjét adja eredményül.

Ez azt jelenti, hogy ezzel a módszerrel nyilvános módszereket kaphatunk a java.lang.Tárgy osztály, mint Sztring, hash kód, és értesítMinden:

@Test public void givenClass_whenGetsAllPublicMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Method [] módszerek = birdClass.getMethods (); List methodNames = getMethodNames (módszerek); assertTrue (methodNames.containsAll (tömbök .asList ("egyenlő", "értesítAll", "hashCode", "séták", "eszik", "toString")); }

Ahhoz, hogy csak az általunk érdekelt osztály nyilvános módszereit kapjuk, ki kell használnunk getDeclaredMethods módszer:

@Test public void givenClass_whenGetsOnlyDeclaredMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Sorolja fel a ténylegesMethodNames = getMethodNames (birdClass.getDeclaredMethods ()); List várhatóMethodNames = tömbök .asList ("setWalks", "séták", "getSound", "eszik"); assertEquals (várhatóMethodNames.size (), actualMethodNames.size ()); assertTrue (várhatóMethodNames.containsAll (actualMethodNames)); assertTrue (actualMethodNames.containsAll (várhatóMethodNames)); }

Ezeknek a módszereknek mindegyikének van egy-egy variációja, amely egyszerest ad vissza Módszer tárgy, amelynek nevét ismerjük:

@Test public void givenMethodName_whenGetsMethod_thenCorrect () dobja a Kivételt {Bird bird = new Bird (); Method walksMethod = bird.getClass (). GetDeclaredMethod ("sétál"); Metódus setWalksMethod = bird.getClass (). GetDeclaredMethod ("setWalks", boolean.class); assertTrue (walksMethod.canAccess (madár)); assertTrue (setWalksMethod.canAccess (madár)); }

Figyelje meg, hogyan kapjuk meg az egyes módszereket, és adjuk meg, hogy milyen paramétertípusokat vesznek fel. Azok, akik nem veszik figyelembe a paramétertípusokat, üres változó argumentummal kapják meg, így csak egyetlen argumentum marad a számunkra, a metódus neve.

Ezután megmutatjuk, hogyan lehet futás közben meghívni egy módszert. Alapértelmezés szerint tudjuk, hogy a sétál attribútuma Madár osztály az hamis, szeretnénk annak hívni setWalks módszert és állítsa be igaz:

@Test public void givenMethod_whenInvokes_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Madármadár = (Madár) birdClass.getConstructor (). NewInstance (); Metódus setWalksMethod = birdClass.getDeclaredMethod ("setWalks", logikai.osztály); Method walksMethod = birdClass.getDeclaredMethod ("sétál"); logikai séták = (logikai) sétákMódszer.invoke (madár); állításHamis (sétál); assertFalse (madár.sétálások ()); setWalksMethod.invoke (madár, igaz); logikai séták2 = (logikai) sétákMódszer.invoke (madár); assertTrue (2. séta); assertTrue (madár.séták ()); }

Figyeljük meg, hogyan hívtuk meg először a sétál metódust, és öntse a visszatérés típusát a megfelelő adattípusra, majd ellenőrizze annak értékét. Ezután később a setWalks módszer az érték megváltoztatására és újra tesztelésre.

9. Következtetés

Ebben az oktatóanyagban áttekintettük a Java Reflection API-t, és megvizsgáltuk, hogyan lehet felhasználni az osztályok, interfészek, mezők és módszerek futás közbeni ellenőrzésére anélkül, hogy a fordítási idővel előzetesen tudnánk a belső részeikről.

Az oktatóanyag teljes forráskódja és példái a GitHub oldalon találhatók.