Mi az a Reflexió?
A reflexió egy olyan API, amely a heap területen betöltött Class típusú objektumok segítségével lehetővé teszi a kívánt osztály példányainak létrehozását, valamint a példányok mezőihez és metódusaihoz való hozzáférést, függetlenül a hozzáférési módosítóktól.
Itt a betöltött osztály azt jelenti, hogy a JVM osztálytöltője befejezte a class fájl betöltését, majd létrehozott egy Class típusú objektumotamely tartalmazza az osztály információit, és eltárolta a heap területen. Fontos megjegyezni, hogy ez eltér a new kulcsszóval létrehozott objektumoktól. Ha nem érti a Class típusú objektumokat, akkor nézze meg a java.lang.Class objektum JDK dokumentációját.
Használati mód
A reflexió használata előtt be kell szereznünk a heap területen betöltött Class típusú objektumot. Háromféleképpen tehetjük ezt meg.
- Osztály.class használatával
- Példány.getClass() használatával
- Class.forName("osztálynév") használatával
Láthatjuk, hogy a három módszerrel létrehozott Class típusú példányok megegyeznek. Mindegyiknek ugyanaz a hash értéke, tehát a helyzetnek megfelelően használhatjuk őket.
Most, hogy megszerezték a Class típusú objektumot, létrehozhatunk egy példányt az osztályból, és hozzáférhetünk a példány mezőihez és metódusaihoz, függetlenül a hozzáférési módosítóktól. Először hozzunk létre egy példányt az osztályból.
A getConstructor() segítségével lekérhetjük a konstruktort, a newInstance() pedig dinamikusan létrehoz egy Member példányt.
Végül férjünk hozzá a példány mezőihez és metódusaihoz, függetlenül a hozzáférési módosítóktól.
A getDeclaredFileds() segítségével lekérhetjük az osztály összes példányváltozóját, a get() metódussal pedig lekérhetjük a mező értékét, a set() metódussal pedig módosíthatjuk. Fontos megjegyezni, hogy a private hozzáférési módosítóval rendelkező mezőkhöz való hozzáféréskor a setAccessible() metódusnak true értéket kell átadnunk.
A metódusokhoz is hasonlóan a getDeclaredMethod() segítségével férhetünk hozzá. Ebben az esetben meg kell adni a metódus nevét és a paraméterek típusát. Hasonlóképpen, a private hozzáférési módosítóval rendelkező metódusokhoz való hozzáféréskor a setAccessible() metódusnak true értéket kell átadnunk. Végül az invoke() metódussal meghívhatjuk a reflexió API-val beszerzett metódust.
Előnyök és hátrányok
- Előnyök
- Futásidőben létrehozhatunk osztálypéldányokat, és hozzáférhetünk a mezőkhöz és metódusokhoz, függetlenül a hozzáférési módosítóktól, ami rugalmasságot biztosít a szükséges műveletek elvégzéséhez.
- Hátrányok
- Sérti a bekapszulázást.
- Futásidőben hozza létre a példányokat, így a fordítási időben nem ellenőrizhető a típus.
- Futásidőben hozza létre a példányokat, így nehezebb megérteni a konkrét működési folyamatot.
- A mezőkhöz és metódusokhoz való hozzáférés lassabb a reflexió használatával, mint közvetlenül. (Nem minden esetben lassabb.)
Miért használjuk?
A reflexió API-val futásidőben hozzáférhetünk az osztályok információihoz, és tetszés szerint manipulálhatjuk az osztályokat. Még a private hozzáférési módosítóval ellátott mezőkhöz és metódusokhoz is hozzáférhetünk. Mivel ez sérti az objektumorientált tervezés egyik alapelvét, a bekapszulázást, ezért úgy tűnhet, hogy nem szabadna használni.
Egy kis konzolalkalmazásnál a fejlesztő könnyen megértheti, hogy mely objektumokat és függőségeket fogja használni a program. De egy keretrendszerhez hasonló nagyméretű fejlesztésnél nehéz nyomon követni a rengeteg objektumot és függőséget. Ebben az esetben a reflexió segítségével dinamikusan létrehozhatunk osztályokat, és meghatározhatjuk a közöttük lévő függőségeket.
Például a Spring Bean Factory-ben, ha csak a @Controller, @Service vagy @Repository annotációkat használjuk, a Bean Factory automatikusan létrehozza és kezeli az annotációval ellátott osztályokat. A fejlesztő nem adott meg információt a Bean Factory-nak az osztályokról, de ez azért lehetséges, mert a reflexiót használja. Futásidőben megkeresi az annotációval ellátott osztályokat, és ha talál, a reflexió segítségével létrehozza az osztály példányait, beállítja a szükséges mezőket, és eltárolja a Bean Factory-ban.
Természetesen, mint már említettük, a bekapszulázás sérülése miatt csak akkor szabad használni, ha feltétlenül szükséges.
Hozzászólások0