Java: A klassz osztály

Bevezetőként tisztázzuk a következőket: Önnek, kedves olvasónak, aki ezt a cikket olvassa rendelkeznie kell bizonyos Java programozási alapokkal, tehát ne ez legyen az első cikk, amit a Java nyelvről olvas el. Másodsorban, szándékaim szerint ez egy több részes cikksorozat lesz, mely felboncolja a Java által nyújtott alacsony színtű objektumkezelési metódusokat. Ez a cikk bevezetőként szolgál, megmutatja az előttünk álló lehetőségeket, és felvet egy érdekes problémát is, mégpedig a dinamikus osztálybetöltés problémáját. Az elkövetkező cikkek még mélyebbre fognak ásni ebben a témakörben. Sok sikert, és kitartást.

Miről is van szó?

Valószínűleg sokan Önök közül nem tudják, hogy mire is lehet használni a Java-ban az egyik alaposztályt, amely a "fantáziadús" Class névre hallgat. Igazuk is van, ez nem igazán a leghasználtabb (és legismertebb) osztály, viszont egy cikksorozatot megérdemel, mert sok érdekesség rejlik e mögött az egyszerű név mögött, és egy pár probléma megoldását igencsak elősegíti ezeknek a rejtett tulajdonságoknak az ismerete.

Viszont mielőtt beleugranánk a mélyvízbe, tisztáznunk kell egy alapvető fogalmat. Mi a különbség egy osztály, és az osztály egy példánya között. Az osztály egy absztrakt fogalom, a példánya pedig egy objektum, mely tartalmazza az osztály metódusait, illetve tulajdonságait. Vegyük például a következő egyszerű kódrészletet:

class Test {

public Test() {

System.out.println("Test Constructor");

}

public static void main(String[] args) {

Test test = new Test();

}

}

Ebben az esetben a Test nem más, mint az osztály. A testObj változó (mert valójában ő egy változó) pedig egy objektum, melyet Test osztály alapján hoztunk létre. Ennek az objektumnak van memóriacíme, elfoglal bizonyos számú bájtot ettől a címtől kezdődően, és tudunk hivatkozni rá és a függvényeire, illetve a tulajdonságaira. Vele ellentétbe, az osztályának nincs elérhető címe, és az osztály semmiképp nem kezelhető úgy, mint egy objektum, hiszen nem az. Ez egy absztrakt fogalom, és az objektumok, melyek belőle származnak, a konkrét példányai. Hiába vannak egy osztálynak tulajdonságai, ha nem tudunk hivatkozni rájuk, hiszen azok valójában csak a példányosított objektumokban jelennek meg. Viszont egy osztályról jó tudni, hogy milyen tulajdonságai vannak, hogy tudjuk, hogy az objektumokban mit használunk.

Nem kell persze elfeledkeznünk a statikus (osztály) metódusokról, illetve a statikus tulajdonságokról se, de ezek tárgyalása nem tartozik ebbe a cikkre. Ennyi bevezető után vágjunk is bele.

Dinamikus betöltések

Amint ki lehetett találni ennyiből, a Java Class osztály pont a fent bemutatott absztrakt fogalmat próbálja kézzelfoghatóvá tenni. Ha elkezdjük böngészni a Java API-t, az első dolog, ami a szemünkbe ötlik, az az, hogy ennek az osztálynak nincs konstruktor függvénye. Erre figyelmeztet az is, hogy a Class osztály példányai akkor jönnek létre, amikor új objektumokat hozunk létre a new paranccsal, vagy valamilyen más módon.

A dinamikus betöltés alapja az, hogy futó alkalmazásban dinamikusan választjuk ki az osztályt, amelyet be akarunk tölteni, és abból példányosítunk egy objektumot. Erre persze rengeteg mód van, és a legtöbb egy sok mérföldes if (haladó programozóknak meg switch) listában merül ki. A Class osztály szolgál egy nagyon elegáns megoldással, amit ebben a cikksorozatban szándékomban áll bemutatni. Ez teljesen kiküszöböli a többmérföldes if-eket, és még a fránya new kulcsszót se kell agyonnyúzni.

Most szerintem felkapta a fejét a kedves Olvasó. Milyen más módszerrel lehet még objektumokat létrehozni. Hát például lehet használni a Class osztály newInstance() metodusát. Ez nem csinál mást, mint az említett osztály alapján létrehoz egy darab objektumot. Vagyis példányosítja az osztályt. Annak érdekében, hogy még világosabb legyen, amit mondani szeretnék, meghívja az osztálynak a konstruktor függvényét.

Egy probléma adódik ezzel a módszerrel, mégpedig, hogy hogyan kapunk mi olyan objektumot, mely Class típusú osztály példánya? Természetesen minden objektumnak van egy olyan metódusa, hogy getClass(), amely visszatéríti az osztályt, melynek az objektum a példánya, de ez kevés és nem is igazán érdekes, hisz egy létező, általunk létrehozott objektumról igazán illik tudni, hogy milyen osztály alapján hoztuk létre.

Másként állunk hozzá a dolgokhoz, ha megvizsgáljuk az osztály (a Class osztály) forName(String) metódusát. A Java API-jának leírásából kiderül, hogy ez a metódus tálcán felszolgálja nekünk azt az osztályt, aminek a nevét paraméterben megadtunk.

Figyelem! Ne keverjük a dolgokat: A Class osztály is csak egy osztály. Viszont a Class osztály egy példánya egy olyan objektum, mely más osztályokat jelképez. Ez alatt a következőt érthetjük: a Class osztály egy példányából létre tudunk hozni egy olyan objektumot, mely olyan típusú mint a Class osztály példánya.

Térjünk vissza a Class osztály forName(String) függvényéhez. Amint mondtam, ez visszaadja azt az osztályt, amelynek a nevét megadtuk a paraméterben. Ha egészen véletlenül melléparamétereztünk, akkor szép Exceptionokat dob. Például egy ClassNotFoundException megmondja, hogy nem talált ilyen nevű osztályt.

Ennél a pontnál már van egy darab osztályunk, tehát nem kell mást tennünk, mint meghívni a Class osztály newInstance() metódusát. És ezzel már kész is lennénk, hisz ennek a metódusnak a visszatérési értéke egy objektum, melyet a mi Class osztályunkból példányosított. A forráskód így néz ki:

class Test2 {

public Test2() {

System.out.println("Test Constructor");

}

public static void main(String[] args) {

try {

Test2 test = (Test2)Class.forName("Test2").newInstance();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

}

Akad a megoldásnak egy kis hátulütője. Ez a metódus csak akkor működik tökéletesen, ha az osztálynak olyan konstruktora van, amely nem vár el paramétert a hívótól. Másképp szép Exception-ök sorozatát adja vissza. Hogy ezt hogy lehet áthidalni, majd a következő részben fogjuk letisztázni, ahol bővebben megismerkedünk egy pár, igencsak szép és hasznos osztállyal, és egyéb ízletes ínyencségek várnak még ránk.

Deák Ferenc