Az építő osztály

Múlt havi számunkban elkezdtük a dinamikus osztálybetöltést, és bővebben megismerkedtünk a Class osztállyal, amely lehetővé teszi, hogy objektumokat tudjunk létrehozni a nevük alapján, anélkül, hogy bármi más információval rendelkeznénk az osztályról. Csak egyetlen bakija volt a bemutatott módszernek: csak olyan osztályokat tudott létrehozni, amelyeknek volt alapértelmezett (paraméter nélküli) konstruktor-függvénye. A mostani cikk bemutatja miként lehet olyan osztályokat létrehozni, ahol a kosntruktor-függvény paramétereket is elvár.

Ha egy picit beleböngészünk a Java API-ba, a Class osztálynál, látni fogjuk, hogy rendelkezik egy olyan metódussal, mely a következőképpen mutat:

Constructor[] getConstructors()

és amint le van írva, ez a metódus visszatérít egy tömböt, amely Constructor objektumokat tartalmaz. Az osztályunk publikus konstruktor függvényeit. Ha az osztály összes konstruktorát le szeretnénk kérdezni (beleértve a privát konstruktorokat is), akkor használjuk a

Constructor[] getDeclaredConstructors()

metódust, amely válogatás nélkül visszadja az összes konstruktort.

Persze, jogos a kérdés, mi ez a Constructor, ha már ennyit szerepeltetjük.

A Constructor osztály

Ha tovább böngésszük az API dokumentációt, megtaláljuk a Constructor osztályt, a következő magyarázó szöveggel: "A Constructor osztály információt szolgáltat egy osztály egy konstruktor függvényéről." A leglényegesebb, hogy a Constructor osztály a java.lang.reflect csomagban található. Ne feledjük beimportálni.

Kutakodjunk tovább a Constructor osztály metódusai közt, aminek eredményeként megleljük a

Class [] getParameterTypes()

metódust, mellyel lekérdezhetjük ennek a konstruktor függvénynek a paramétereit, amelyeket elvár. Vigyázzunk viszont ezzel a metódussal, mert nagyon könnyen végtelen ciklusba kerülhetünk, ha automatikusan próbáljuk elvégeztetni a feladatot.

És most jön a lényeg, az

Object newInstance(Object[] arguments)

metódus. Mint ahogy a paramétertípus kéri, létre kell hoznunk egy tömböt, amely tartalmazza azokat az objektumokat, melyeket át szeretnénk adni az osztálynak, hogy azok alapján hozza létre az új objektumot.

A newInstance metódusnál a következőkre kell figyelnünk:

  • Ha absztrakt osztályt akarunk létrehozni, akkor kapunk egy InstantiationException kivételt.
  • Ha nem elérhető a konstruktor (értsd ezalatt: privát konstruktor) akkor kapunk egy IllegalAccessExceptiont
  • Ha a paraméterek száma nem talál, akkor IllegalArgumetnExceptiont vált ki.

Van viszont egy kis probléma a primitív típusokkal (int, float). Ezek nem igazán objektumok, mégis egy Object[] tömbbe kell berakni őket. A megoldás az, hogy használjuk a primitív típus wrapper osztályát (pl. az int-nek az Integer). Sikertelen konverzió esetén megint egy IllegalArgumentExceptionnal találjuk szembe magunkat.

Ha a konstruktor a maga során dob egy kivételt, akkor a newInstance metódus egy InvocationTargetException kivételt dob, amelynek átadja a dobott kivételt.

És végül nézzük a következő példát:

import java.lang.reflect.*;  //kell a Constructornak

 

class Test {

      public Test(String arg1, int arg2) {

            System.out.println(arg1+" "+arg2);

      }

}

 

public class Default {

      public static void main(String[] args) {

            try {

                  Class test = Class.forName("Test");

                  Constructor cons[] = test.getDeclaredConstructors();

                  String a = "Hello Constructor";

                  int b=2;

                  Object paras[] = {a,new Integer(b)};

                  Test testClass = (Test)(cons[0].newInstance(paras));

            }

            catch(Exception ex) {

                  ex.printStackTrace();

            }

      }

}

Kísérletezgessünk bátran az itt bemutatott kódrészlettel, hisz bántódásunk nem eshet. Legközelebb más lesz a napi menün.

Deák Ferenc