10. fejezet

Nem csak számok vannak a világon! Dolgozzunk érdekesebb adatokkal: karakterek és azok halmazai. Karaktertípus a Jávában, a char típus. Karaktersorozatok avagy ismerkedés a String osztállyal. String és StringBuffer, a két jóbarát.

Talán már kicsit unalmas, hogy példáink mindig számokról szólnak. Ugyan szövegeket állandóan írunk ki, de nem tudunk velük olyan könnyedén variálni, mint a számokkal. Ezen lecke végére ez a hiányérzetünk is megszûnik, mert most a Jáva karakterkezelési eszközeivel foglalkozunk. A számítógép ugyanolyan könnyedén tárol és manipulál karakter típusú adatokat (emlékszel az elsõ leckére? A karakterek a számítógép által ábrázolható összes betû, számjegy, jel összessége), mint számokat. Számára természetesen ezen adatoknak semmi jelentése nincsen, az egymás után tárolt a,l,m és a betûk semmilyen módon nem idézik fel benne a gyümölcsöt, mint ahogy a 2001 értékû egész típusú szám sem jelenti számára a mostani évet. Minthogy a számítógép nem magának számol, hanem nekünk, így aztán elég, ha a karaktereknek csak számunkra van jelentése.

A karakterek tárolására szolgáló alaptípus a char. Egy char típusú változó egy karaktert képes tárolni. Értékül létezõ karakter típusú érték vagy karakterkonstans adható. Példa:

char c;
c = 'A';

A c változó értéke most tehát az 'A' karakter, egészen pontosan annak a kódja. A számítógép számokkal képes dolgozni, így a karaktereket is számokként ábrázolja, minden karakternek saját kódja van. A számítógépes gyakorlatban millióféle karakterkódolás létezik, a Jáva belsõleg a Unicode karakterkészletet használja. A Unicode Jáva által használt változata nem egy, hanem két bájton ír le egy karaktert, így több, mint 65000 karaktert képes ábrázolni. A fenti gondolatmenet eredménye az, hogy char és egész típusok egymásba alakíthatók, minthogy mindegyik csak egész szám. Példa:

int i = (int)c;
char d = (char)i;

Feladat

Írj egy programot, ami kiírja a Jáva karakterkészletet 32 és 127 között, a határokat beleértve. Egy sorba írd ki a karakter kódját majd a karaktert magát is és ezt végezd el az összes kódra. Nagyon egyszerû feladat, remélhetõen menni fog, ha nem, itt van a megoldás.

Igazában az esetek többségében nem egyedi karakterek érdekelnek, hanem azokból összeállított sorozatok, karaktersorozatok vagyis népszerû angol nevükön stringek. Stringet könnyedén csinálhatnánk karakterekbõl készített tömb segítségével

char string[] = new char[20];

a Jáva azonban elõzékenyen rendelkezésünkre bocsátja a String osztályt, teljes nevén java.lang.String-et. A csomagokról, mint például a java.lang majd a következõ fejezetben olvasunk, most elég annyi, hogy ez az osztály a beépített osztálykönyvtár része és alapból a rendelkezésünkre áll, nem kell érte semmit tennünk, hogy felbukkanjon. A String egy nem megváltoztatható karaktersorozat. Ez azt jelenti, hogy egy Stringet ha egyszer létrehoztunk adott szöveggel, akkor a szöveg a továbbiakban nem változtatható meg. Ez nem tûnik túl ígéretesnek, viszont a megváltoztathatatlan String egyedet felhasználhatjuk további Stringek építésére.

Stringet lértehozni nagyon egyszerû.

String s = new String( "Hello, Jáva" );

A String tehát egy mezei objektum, olyan, amilyeneket eddig láttunk, kivéve, hogy nem nekünk kellett definiálnunk, hanem már megtették helyettünk. Az s egy String egyedre mutató referencia, ilyet is láttunk már. Egy trükk van a képben: a "Helló, Jáva" konstans. A String egy kivételes osztály a Jávában abban a tekintetben, hogy String típusú konstansokat a nyelv közvetlenül támogat. A "Helló, Jáva" igazából létrehoz egy String egyedet, amiben a "Helló, Jáva" string van, majd ennek alapján a new String létrehoz egy új string egyedet. Nem túl hatékony, én is csak azért írtam le, hogy határozottan megmutassam, hogy a String is csak egy objektum. Igazából elegendõ lenne ennyi:

String s = "Hello, Jáva";

Nézzük, mit is csináltunk elõbb. Itt a soha vissza nem térõ alkalom, hogy egy pillantást vessünk a Jáva könyvtár leírására, ami elérhetõ a weben vagy letölthetõ a Sun-tól a JDK weblapjáról (a cikk írásának a pillanatában a Java 2 1.3-as változata a legújabb. Keressük meg innen kiindulva a JDK API dokumentációját és nézzük a String lapját! Megtalálhatjuk a választ, hogyan mûködött az elsõ sor. A Stringnek van egy konstruktora, ami Stringet fogad.

String(String value);

Ezt használtuk fel az imént. Két sorra bontva:

String t = "Hello, Jáva";
String s = new String( t );

De sokat beszéltünk errõl az egyszerû sorról, nézzünk valami érdekesebbet! Tekintsük a következõ jól ismert sort:

public static void main( String args[] ) ...

Hát igen, ez a main definíciója. Most már megérthetjük a paraméter részét is: a main egy Stringekbõl álló tömböt kap, mindegyik Stringben egy paraméter. Ha tehát a programot így hívjuk meg:

java Program P1 P2 P3 P4

akkor a main egy 4-elemû tömböt fog kapni, a tömb elemeiben egy-egy String egyedre van referencia, és ezek a String egyedek sorban a P1, P2, P3 és P4 karaktersorozatokat tárolják. Amint a tömböknél tanultuk, minden tömbnek van egy length nevû egyedváltozója, ami megadja a tömb hosszát. Az összes paraméter kiírása ezek után nem nehéz:

for( int i = 0 ; i < args.length ; ++i )
  System.out.println( args[i] );

Írjunk most rövid programot, ami kiírja az összes paraméterét, amiben megtalálható az "al" karaktersorozat. Tehát ezeket mind kiírja: alma, fal, falu de nem írja ki az akol vagy az olaj szavakat. Alaposan végigtanulmányozva a String metódusainak leírását, megtaláljuk az indexOf(String str) metódust, ami megkeresi a String egyedben, amire meghívták a paraméterül kapott stringet és megmondja a pozícióját ill. -1-et ad vissza, ha nem találja. A program igazán egyszerû, de itt a megoldás ellenõrzésképpen. Ha megvan, írd át úgy a programot, hogy a keresett részletet kiemeli úgy, hogy elé és mögé _ jeleket tesz, pl. _al_ma, t_al. Ehhez a substring metódusra lesz szükséged, ellenõrizheted a megoldást itt.

Szép dolog, hogy van egy megváltoztathatatlan String-ünk, de sokkal érdekesebb lenne, ha felhasználhatnánk más String-ek alkotására. Két String-bõl egy harmadikat csinálni Jávában nagyon egyszerû, mert String objektumokra definiálva van a + operátor és összefûzést jelent. Példa:

String s1 = "eleje";
String s2 = "vége";
String s3 = s1 + s2;

A dolog végén s3 az "elejevége" szöveget fogja tartalmazni. Egy baja van ennek a megoldásnak: ha sokat használjuk, jócskán teleszemeteli a memóriát, minthogy minden lépésben egy nem változtatható String keletkezik. A Jáva készítõi a változtatható StringBuffer könyvtári osztállyal oldották meg a problémát.

A StringBuffer arra való, amire a String nem alkalmas: karaktersorozatok manipulálására. A StringBuffer képes a benne levõ karaktersorozat végére egy másikat fûzni, törölni, felülírni a tartalom egy részét vagy beszúrni tetszõleges pontra. A könnyedségnek persze ára van: a StringBuffer több helyet foglal, mint egy String. A legjobb, ha mindkettõt a helyén használjuk és ez nem nehéz, mert mindkettõnek van olyan konstruktora, amely Stringet vagy StringBuffert tud csinálni a másikból. Mondhatjuk tehát:

String s = "Hello";
StringBuffer sb = new StringBuffer( s );
String s2 = new String( sb );

Igazából a Jáva fordító a Stringek összefûzését is StringBufferrel oldja meg: eleje-vége példánknál elõször egy ideiglenes StringBuffer jön létre, ebben összefûzõdik a két String, majd ebbõl legyártódik az s3-ba kerülõ eredménystring. Ha mondjuk egy jóféle hurokban tesszük ezt, könnyedén legyárthatunk néhány száz ideiglenes objektumot.

Feladat

Írj egy programot, ami összefûzi a paramétereit egy Stringgé és ezt a Stringet kiírja. A paraméterek között _ jelek legyenek. Hozz létre egy StringBuffert, ebben fûzd össze a paramétereket, majd az eredményt alakítsd Stringgé és írd ki! Íme a megoldás ellenõrzésképpen.

Ellenõrzõ kérdések

Kovetkezo lecke Tartalomjegyzek