java nyelv programozoknak
TRANSCRIPT
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 1/80
Java nyelvprogramozóknak Mottó: Elmondod, elfelejtem. Megmutatod, tán megjegyzem. Ha együtt csináljuk,
akkor megértem. (Kínai közmondás)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 2/80
1. Bevezetés
1.1. A Java nyelv tör ténete
1991-ben a Sun Microsystems egy 13 f ő ből álló fejlesztői csoportot
állított fel „Green Team” fantázianévvel. A csoport feladata olyanháztartási eszközök készítése volt, amelyek beépített mikrocsippelrendelkeznek, s képesek az egymás közötti kommunikációra. Kezdetben a C++nyelvvel próbálkoztak, de gyorsan kiderült, hogy ez a nyelv nem alkalmas afeladatra, ezért a csapat egyik tagja (név szerint James Gosling) egy új nyelvetdolgozott ki. Az új nyelv a C egy továbbfejlesztett verziója, amelyből viszontkihagytak olyan elemeket, amelyek a hibalehetőségek miatt megkeserítették a C
programozók életét (pl. mutatók, struktúrák, dinamikus memóriahasználat..) A nyelva tűzkeresztségben az „Oak” (Tölgy) nevet kapta, állítólag azért, mert kifejlesztő jedolgozószobájának ablakából egy hatalmas tölgyre látott rá. A nyelvvel szemben
támasztott alapvető elvárás volt, hogy platformfüggetlen legyen, hiszen a háztartásieszközök gyártói bármikor lecserélhették mikroprocesszoraikat egy olcsóbb, jobbmodellre.
A kezdeti sikereknek köszönhetően a projekt új lendületet kapott, újabbembereket vontak be a munkába, így a létszám 70 f őre duzzadt, s felvette a„FirstPerson” nevet. A biztató eredmények ellenére sem sikerült nagyobbmegrendelést szerezniük, így 1993 tavaszára a projekt végveszélybe került. Ekkor avezetők (John Gage, James Gosling, Bill Joy, Patrick Naughton, Wayne Rosing ésEric Schmidt) három napra elvonultak a világ elől egy vidéki szállodába, s ott
határoztak a továbbiakról. Döntésük eredménye, hogy meg kell próbálkozni azInternettel!
Az grafikus böngészők megjelenésének köszönhetően egyre nagyobbnépszer űségnek örvendő Internet számára tökéletesen alkalmas volt az Oaktechnológia, hiszen platformfüggetlenségének köszönhetően nem okozott számáragondot a hálózatba kapcsolt gépek inhomogenitása. 1995 elejére a csapat kifejlesztettegy grafikus böngészőt „Webrunner” néven, amely akkor került az érdeklődésközéppontjába, amikor a statikus lapok között felbukkant egy egérrel mozgathatóháromdimenziós molekula. Késő bb ez a böngésző lett az őse HotJava böngészőnek, s
itt jelent meg a Java kabalafigurájaként ismert Duke figura. A Sun megpróbáltalevédeni az Oak nevet, de kiderült, hogy ezt már használják egy programozási nyelvelnevezéseként, így új nevet kellett találni. A nyelv kifejlesztésének ideje alattelfogyasztott kávék származási országának emléket állítva kapta a technológia a Java nevet. A csapat külön Internet-címet kapott, ahol lehetővé tették a források ingyenesletölthetőségét, s így bárki számára a tesztelési lehetőséget. A letöltések számarohamosan növekedett, s 1995 novemberében már letölthető volt a nyelv bétaverziójának forráskódja és fejlesztőkészlete. Néhány év alatt a Java a programozókegyik legfontosabb eszköze, a hálózat nyelve és operációs rendszere lett. Mindezazoknak a lelkes programozóknak köszönhető, akik korán felismerték a
platformfüggetlenség iránti igényt, s meglátták a benne rejlő lehetőséget.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 3/80
1.2. A Java platformfüggetlensége
Napjaink - magasabb szintű programozási nyelven írt - alkalmazói szoftvereihardverfüggetlenek. Ez kicsit szemléletesebben azt jelenti, hogy egy adott operációsrendszerre írt felhasználói programnak nem kell tör ődnie azzal, hogy milyen hardver
van a gépünkben. Nem kell ismerettel rendelkeznie a memória vagy a háttértárolótípusáról, gyártójáról. A hardverek típus- és gyártóspecifikus részeit a gépen futóoperációs rendszer elrejti a felhasználói programok elől, egy egységes felületet
biztosítva ezáltal a programozóknak. A Java viszont ennél is tovább ment, hiszenmég egy réteget húzott az operációs rendszerre, így elf edve a rendszerek közöttikülönbségeket. Ezt a réteget Java Virtuális Gépnek (JVM1) nevezték el. (Ábra 1-1)
Ábra 1-1 Platformok rétegződése
A JVM-nek, illetve a mögötte rejlő koncepciónak köszönhetően létrejött egy új,magasabb absztrakciós szintű platform (Java platform), amely lehetővé teszi, hogy
az egyszer már megírt programunkat bármely más architektúrán futtassuk. (Innenszármazik a Java alapfilozófiáját megfogalmazó „Írd meg egyszer, futtasd bárhol!”mondat) Természetesen egy platform csak akkor válhat Java platformmá, ha az adottszoftver, vagy hardver gyártója beépítette a Java programok futtatásához szükségesJVM-et.
1.3. A Java alkalmazásai, lehető ségei
Ízelítőként álljon itt néhány példa, melyből kitűnik a Java technológia2 sokszínűsége. Az első és legfontosabb tény, hogy minden jelentősebb operációs
rendszerhez ingyenesen elérhető
legalább egy JVM, ennek köszönhető
en egyáltalunk megírt és lefordított program gond nélkül futtatható Solarisos, Windowsos,Linuxos, AS/400-as, stb. gépeken (PC-n és más architektúrán egyaránt). Sokan aJava-t az appletek programozásaként ismerik, de a webböngészők által végrehajtható
programok írása csak egy nagyon kis szelete a technológiának. A lehetőségeknekszinte csak a képzelet szabhat határt. Egyszer ű eszközök segítségével készíthetünk
párhuzamos programokat, adatbázis-kezelő alkalmazásokat (JDBC), dinamikusweboldalakat (Servlet, JSP), vagy a napjainkban oly divatos XML feldolgozókat
1
JVM – Java Virtual Machine (Java Virtuális Gép)2 A Java nemcsak egy nyelv, hanem egy technológia elnevezése is egyben, amely a Java nyelvet, mint eszközthasználja céljai megvalósítására
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 4/80
illetve webszolgáltatásokat. Van Java-ban írt webböngésző, webszerver, de mégoperációs rendszer is.
A Java nem állt meg a személyi számítógépek által futtatható alkalmazásoknál.Létezik JVM mobiltelefonokra, PDA-kra, amelyek – bár szűkebb eszközkészlettelrendelkeznek – képesek Java programok használatára. Ugyanakkor kifejlesztettekJava-kódot futtató processzort, valamint plasztik kártyát (JavaCard) is, amelynekmérete megegyezik egy átlagos bankkártya méretével. A budapesti 56-os villamosvégállomásán a vezetők gyűr ű jüket egy rögzített eszköz elé tartják, hogy azregisztrálja a megérkezést. A rögzített eszköz és az elétartott gyűr ű egyaránt Javakódot futtat, ennek a technológiának a segítségével végezvén el a kommunikációt.Emellett egyre több gyártó jelenti be Java-kód futtatására alkalmas háztartásieszközét is. Ebből látszik, hogy a fejlődés még nem állt meg. A technológiát egyreszélesebb körben alkalmazzák, s fogják alkalmazni a jövő ben is. Természetesenennek a kurzusnak nem lehet célja az itt felsorolt alkalmazási lehetőségekmindegyikének bemutatása, de egy nagyon jó alapot nyújthat, amelyet felhasználvamár bárki elindulhat a számára szimpatikus úton.
1.4. Eszközök és verziók
A felhasználandó eszközök kiválasztása során törekedtünk arra, hogy mindenkiszámára elérhető, s bárhol használható szoftvereket használjunk. Természetesen aJava-hoz is léteznek RAD3 eszközök, amelyekkel - nevüknek megfelelően –gyorsabban készíthetjük el a kódokat, de egy ilyen fejlesztőkörnyezet használatamagában rejti azt a veszélyt, hogy elveszünk a menüpontok között, s „nem látjuk a
fától az erdőt”, vagyis egy fellépő hiba esetén nem tudjuk eldönteni, hogy pontosanhova is nyúljunk. A RAD eszközöknek megvan az előnyük, de ezeket csak akkortudjuk igazán kihasználni, ha már tisztában vagyunk a részletekkel4.
Ezen okokat mérlegelve fejlesztéseinkhez egy egyszer ű szövegszerkesztőt,valamint egy ingyenes fejlesztőkészletet (JDK 5) fogunk használni.(Szövegszerkesztő minden operációs rendszeren található, a JDK pedig letölthető ahttp://java.sun.com/products/jdk internet-címr ől) Amellett, hogy Sun meghatározta aJava nyelvi szabályainak leírását (szintaktikáját), létrehozott egy API6-t, amely aszoftverek által felhasználható osztályokat tartalmazza. Ezeket az osztályokat,
valamint a hozzájuk tartozó segédprogramokat (fordító, futtató, stb.) adják ki JDKnév alatt, különböző verziószámokkal (1.1, ...,1.2.2, ..., 1.4). Ez a verziószámazonban nem felletethető meg egyértelműen a Java-platform verziószámával. Egykiadás dátumát is feltüntető összehasonlítást mutat a Táblázat 1. Az 1.2-es platformúj nevet kapott (Java 2). Ez a jelenleg használt platform, a JDK fejlődése viszontnem állt meg. Újabb és újabb osztályok kerülnek be, igazodván az újabb igényekhez.Meg kell említeni még egy betűszót, ez a JRE7, amely egy lebutított JDK-nak
3 RAD – Rapid Application Development (Gyors Alkalmazás-fejlesztés)4 A Sun oldaláról (www.sun.com) ingenyesen letölthető a Forte nevű fejlesztőkörnyezet (RAD)5
JDK – Java Development Kit (Java Fejlesztői Eszközkészlet)6 API – Application Programming Interface7 JRE – Java Runtime Enviroment (Java Futtató Környezet)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 5/80
fogható fel. Ez az eszköz nem tartalmaz fordító, csak futtató környezetet, amelyakkor lehet hasznos, ha valakinek, például a megrendelőnknek, nincs szüksége ameglévő szoftver fejlesztésére, csak annak futtatására. Ekkor helytakarékossági és
biztonsági szempontból is érdemesebb egy JRE-t telepíteni, amelynek verziószámaanalóg módon növekszik a JDK verziószámával együtt.
Kiadás dátuma Platform verziója JDK verziója
1995. május 23 1.0 1.0
1996. december 1.1 1.1
1.2
1.3
Java 2
1.4
Táblázat 11.5. A Hello Vilag program Java-módra
Általános programozási nyelveknél megszokhattuk, hogy egymegírt forráskódot lefordítva egy futtatható állományt kapunk Ez egyúgynevezett natív kód, amelyet a processzorunk értelmezni, és jó esetben
végrehajtani képes. Java-ban történő programozás esetén ezt a futtatást két lépésre bontjuk fel. Először egy fordító segítségével létrehozunk egy bytecode-ot, amitátadva a JVM-nek végrehajtódik a program. Ilyen megközelítésből szemlélve alétrehozott bytecode a JVM natív kódjának feleltethető meg, amelyet a Java platform
alakít át rendszerspecifikus utasításokká. A JDK-t használva ezeket a lépéseket egy-egy parancssori program segítségével tehetjük meg. A programok a JDK telepítésikönyvtárának bin alkönyvtárában találhatóak. (<JavaHome>/bin) Ezt a könyvtáratérdemes a <PATH> környezeti változóban tárolni annak érdekében, hogy ne kelljenminden fordításkor és futtatáskor a teljes elérési útvonalat megadni. (A környezetiváltozók létrehozása és módosítása platformfüggő, így erre nem adhatunk egységesmegoldást.) Emellett szükség van a <CLASSPATH> környezeti változóra is,amelyben azokat a könyvtár-elérési utakat tároljuk, ahol osztályaink találhatóak.(Tipikusan szerepel benne az aktuális könyvtárat jelképező ’.’, mint lehetségeselérési útvonal, illetve a Java telepítési könyvtára)
Példa 1.1 A Hello Vilag programunk forrása/ * Hel l o. j ava * /publ i c cl ass Hel l o{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {Syst em. out . pr i nt l n( ”Hel l o Vi l ag! ”) ;
}}
Első programunknak nem az a célja, hogy mindent megértsünk. Az elsődlegescél az, hogy tisztában legyünk az alapvető szabályokkal, valamint le tudjunk
fordítani és futtatni egy Java nyelven írt programot.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 6/80
- Az első ilyen szabály, hogy néhány operációs rendszerrel ellentétben a Javakülönbséget tesz kis-, és nagybetűk között, ezért erre fokozottan ügyelnünkkell!
- A második szabály, hogy a forrásfile nevének meg kell egyezni a bennedefiniált objektumosztály nevével, kiterjesztése pedig a java (Esetünkben tehátHello.java)
A fordítás és futtatás folyamata tehát két részre osztható fel.(Ábra 1-2) Előszöra javac8 programnak paraméterként átadva az elkészült Hello.java file-t, létrejön egyHello.class file. Ez az úgynevezett bytecode. A class file-unkat a java program
paramétereként futtathatjuk. Újabb szabály, hogy a javac esetén ki kell írni akiterjesztést, míg a java program esetén tilos azt megadni. Tehát a kiadandó
parancsok összefoglalva:- javac Hello.java – Ennek hatására létrejön a Hello.class- java Hello – A Hello.class file futtatása (Az üdvözlő szöveg képernyőre írása)
Ábra 1-2 Egy Java program állapotátmenetei
Itt kell megemlítenünk, hogy a Java specifikáció alapján két részre oszthatjuklefordított byte-kódjainkat. Az egyik a futtatható, a másik a nem futtatható byte-kód.
Nevükből adódóan a lényeges különbség, hogy az első közvetlenül nem adható át aJVM-nek. A futtatható kód forrását a megfelelően minősített és paraméterezett mai n metódus teszi felismerhetővé. (Ezt láthattuk a Hello programunkban.) A legrövidebbJava kódot a Példa 1.2 mutatja. Ez önálló fordítási egység, tehát a javac programnakátadva lefordul, és létrejön a megfelelő class file. Viszont ha a létrejött byte-kódotfuttatni próbáljuk, hibaüzenetet kapunk. A legrövidebb futtatható kódot a Példa 1.3
mutatja. Ez lefordítható, és hiba nélkül futtatható.
Példa 1.2 A legrövidebb önálló, fordítható egységcl ass A{}
Példa 1.3 A legrövidebb futtatható Java programcl ass A{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {}
}
8 javac – Java Compiler (Java Fordító)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 7/80
1.6. Az OOP9 alapjai
Mielőtt tovább haladnánk, meg kell vizsgálnunk a Java alapját képző objektumorientált paradigmát. A Java „tiszta” OO nyelv, amely azt jelenti, hogy nincs mód az„objektumokon kívüli” programozásra (ellentétben a C++-szal), ezért mindenkinek
ismernie kell az alapfogalmakat és azok jelentését. Bevezetőként az OOP-r ől annyitérdemes tudni, hogy a 60-as évek végére Norvégiában (az Ericcson fejlesztéseinekköszönthetően) már megfogalmazódott az objektum-orientáció lényege, s megjelentaz első OO elveket követő programnyelv is (Simula-67), viszont ekkor még nemterjedt el igazán. Egyrészt ekkor még nem voltak adottak a feltételek egy ilyen
bonyolultságú modellezésre, nem álltak rendelkezésre a megfelelő szabványok,eszközök a fejlesztéshez. Másrészt az új paradigma nagy szemléletváltást igényelt a
programozók részér ől, s ezt nagyon sokan nem tudták felvállalni, a legtöbben inkábba már jól bevált módszereket alkalmazták továbbra is fejlesztéseikhez, kisebbkockázatot vállalva ezzel. Valamint a kezdeti időkben még látták a paradigmában
rejlő előnyöket, er ősségeket, idő kellett ahhoz, hogy ezek kiforrjanak,tudatosodjanak.
A 80-as évek végére viszont már annyira megnőtt az igényelt szoftver-rendszerek komplexitása, s a személyi számítógépek elterjedésével megnőtt az igényaz igényesebb, gyorsabban kidolgozott, felhasználóbarátabb szoftverek iránt, így azeddigi strukturált módszerekkel nem lehetett eleget tenni a növekvő felhasználóielvárásoknak. A kialakult helyzet (szoftver-krízis) megoldására a fejlesztők egyflexibilisebb megoldást kerestek, s újra előtérbe kerülhetett az OOP. Kezdetben mégcsak a programozási nyelvek kezdték sorra bevezetni az OO fejlesztésekhez
elengedhetelen kulcsszavakat, majd a szemlélet kiterjedt a teljes szoftverfejlesztésiciklusra. Jelenleg az igényfelméréstől az implementáláson át a rendszerkövetésigminden fejlesztési fázisra van OO szemléletű megoldás.
Napjaink legelterjedtebb OO nyelvei: Java, C++, Smalltalk, Eiffel, Pascal,CLOS (Common Lisp Object System) Ezek közül a Java, a Smalltalk és az Eiffeltisztán OO nyelvek, míg a többi hibrid nyelv, tehát OO és strukturált programozásrais alkalmas. Ez nem feltétlenül előny, hiszen a szemléletmódok váltogatása sok hibaforrása lehet. (A legtöbben úgy fogják fel, hogy a class egy újabb kulcsszó a C++-
ban, amit meg kell tanulni, s nem érzékelik a szemléletek közötti különbségeket)
1.6.1. Egységbezárás
Az OOP hatékonyságának legf ő bb mozgatórugója, hogy elődeinél közelebb állaz emberi gondolkodáshoz. Nem a rendszer folyamatai felől közelít a megoldáshoz,hanem megpróbálja megérteni, hogy az adott problémát milyen objektumokegyüttműködése oldhatná meg. Nem a feladat egzakt függvényekre való bontásárólvan szó, hanem a valós világ lényegi elemeinek modellezésér ől. Egy-egy ilyenobjektum tulajdonságokkal és viselkedési jellemzőkkel rendelkezik, s a rendszerezeket egységesen kezeli. Nem válnak külön az adatábrázolást végző elemek és azadatok manipulálását végző műveletek. (Ábra 1-3)
9 OOP – Object Oriented Programming (Objektum Orientált Programozás)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 8/80
Ábra 1-3 Objektum = adat + kód egysége
Például egy ember objektumnak van neve és életkora; ezek a tulajdonságaitleíró elemek, a továbbiakban adattagok. Emellett képes járni, beszélni, nevetváltoztatni, amelyek az objektum viselkedését leíró műveletek, a továbbiakban
metódusok.A megegyező adattagokkal és metódusokkal rendelkező objektumokat
osztályokba sorolhatjuk, így könnyítve meg a leírásukat. Az osztály és objektumközötti különbséget a strukturált programok típusai és változói közöttikülönbségéhez hasonlíthatjuk. Ezt az analógiát követve az osztály a típusnak, azobjektum a változónak felel meg. Az osztályban leírt adattagok bizonyos értékeketvehetnek fel, ezzel definiálva egy értékkészletet, míg ezen értékkészlet egyelőfordulása az objektum. Az elő bbi példánál maradva az ember az osztály, s mindenembernek tekinthető, aminek van neve, életkora, valamint képes beszélni, járni és
nevet változtatni. A 11 éves Pisti viszont egy objektum, hiszen a lehetséges emberekközül ő képviseli az egyiket. Két objektum akkor, és csak akkor tekinthető azonosnak, ha mindketten ugyanazt a valós objektumot reprezentálják, tehát azegyenlőségnek nem elégséges feltétele az adattagok értékeinek páronkéntiegyezősége. (Nem minden 11 éves Pisti nevű ember tekinthető ugyanannak azobjektumnak)
1.6.2. Adatelrejtés, üzenetküldés, interfész
Az osztályok leírásánál dönthetünk arról, hogy melyek azok az adattagok,illetve metódusok, amelyekr ől más osztályok objektumai is tudhatnak, amelyet más
objektumok is manipulálhatnak, használhatnak, valamint melyek azok, amihez csakaz adott objektum férhet hozzá. A más objektumok számára nem engedélyezetthozzáférésű adattagokat és metódusokat elrejthetjük a többiek elől.
Az objektumok üzenetküldések útján kommunikálnak egymással. Ez azüzenetküldés azt jelenti, hogy egy objektum megkér egy másik objektumot egyfeladat elvégzésére. Azoknak a metódusoknak az összességét, amelyeken keresztülegy objektum megkérhető valamilyen feladat elvégzésére, az objektum interfészéneknevezzük. Minden objektum rendelkezik egy interfésszel, így minden objektumfelkérhető bizonyos feladatok elvégzésére. (Ha egy objektum nem rendelkezne
interfésszel, akkor nem lehetne megkérni semmire, így nem vehetné ki részét amunkából, következésképpen nem lenne értelme létezésének)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 9/80
Ábra 1-4 Interfészek értelmezése
Az interfész és az adatelrejtés kombinációjával biztosítható, hogy egy objektumkritikus adattagjait csak ellenőrzötten változtathassuk, illetve változtathassanakmások. A megoldás, hogy az adattagokat elrejtjük, s felveszünk az interfészbe egy-
egy olyan metódust, amely képes a kívánt adattag módosítására. Az új értékérvényességének vizsgálatát, s az esetleges figyelmeztetést az újonnan felvettmetódus végzi minden változtatás előtt.
1.6.3. Öröklés
Egy új osztály definiálásának legegyszer ű bb módja, hogy felsoroljuk adattagjaités metódusait. Az OOP viszont nyújt egy ennél sokkal hatékonyabb módszert, azöröklést. Az öröklés két osztály között fennálló kapcsolat, amely során az egyikosztály rendelkezik a másik osztály összes tulajdonságával (adattagjait és metódusaitsajátjaként kezeli), s ezeket újabbakkal egészíti ki. Az létrejövő új osztályt
leszármazott osztálynak, míg a másik osztályt ős osztálynak nevezzük (Ábra 1-5).Természetesen a létrehozott új osztály is lehet más osztályok őse, így egy öröklési fátépíthetünk fel, ahol minden osztálynak meghatározhatóak az ősei és leszármazottai.
Ábra 1-5 Öröklődés
Az öröklés felhasználásának két változatát különböztethetjük meg. Az egyik azáltalánosítás, a másik a specializáció. Specializációról akkor beszélhetünk, ha egymár meglévő osztályt felhasználva, ahhoz új tulajdonságokat adva hozzuk létre az újosztályt, míg az általánosítás esetén a meglévő osztályaink közös tulajdonságaitemeljük ki egy közös ősosztályba.
Különbséget kell még tennünk az egyszeres és a többszörös öröklés között. Azegyszeres öröklés azt jelenti, hogy egy adott osztálynak csak egyetlen közvetlen őse
lehet, többszörös öröklés megvalósításakor pedig az újonnan létrehozott osztályunkakár több ősosztálytól is származtathat adattagokat és metódusokat.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 10/80
1.6.4. Polimorfizmus
A polimorfizmus többalakúságot jelent, amelyet az OOP-n belültöbbféleképpen is értelmezhetünk. Az egyik formája abból adódik, hogy aleszármazott osztály örökli ősének minden tulajdonságát, így annak interfészét is.
Ebből következőleg a leszármazott megkérhető minden olyan művelet elvégzésére,amelyre őse megkérhető. Ezt kihasználva az OO programban minden olyanváltozóhoz, amelynek típusa egy adott ősosztály, hozzárendelhető az ősosztályvalamely leszármazottjai is.
Más megközelítésben a polimorfizmus azt jelenti, hogy ugyanazok a műveletekeltér ő viselkedést mutatnak más osztályokban. Például mást tesz egy általános emlő s, és mást tesz egy belőle származtatott delfin, ha megkérik arra, hogy menjen.
A harmadik értelmezés alapja a metódus-túlterhelés. Ez azt jelenti, hogy egy
adott osztálynak több azonos nevű
metódusa lehet, ha azok a paraméterek típusában,vagy sorrendjében eltérnek egymástól. Ilyenkor egy metódus többalakúságáról beszélhetünk.
2. Vezérlési szerkezetek
Az elméleti bevezető után térjünk rá a gyakorlatra. Az objektumok metódusait astrukturált programozás függvényeihez és eljárásaihoz lehet hasonlítani. Azobjektum a hozzá érkező üzenet hatására egy függvényt hajt végre. Ezekben afüggvényekben használhatjuk a már jól megszokott vezérlési szerkezeteket, ígynövelve kódjaink hatékonyságát. A Java a C programozási nyelven alapul (néhányantévesen egy lebutított C++-nak aposztrofálják), ezért az itt ismertetett szerkezetek aC-t vagy C++-t ismer ők számára nem okozhat nagy meglepetéseket.
2.1. Alapfogalmak
A programozási nyelvek többségéhez hasonlóan a Java-ban is létrehozhatunkváltozókat bizonyos értékek átmeneti tárolására. Változó a kód bármely részénlétrehozható10, viszont csak abban a blokkban használható, amelyben őt definiálták.Különbséget kell tennünk adattag és változó között. Mindkettő rendelkezik típussalés névvel, de a változó csak lokálisan létezik, míg az adattag az objektum
alkotóelemeként bármely metódusból elérhető. Emellett egy változónak mindig kellkezdőértéket adni használat előtt, az adattag viszont felvehet egy típusától függő alapértelmezett értéket. A változó nevének hossza tetszőleges, de betűvel kell hogykezdődjön, majd betűket és számokat tartalmazhat. A betűk mellett használható az _és a $ jel is.
A változó típusa valamely primitív típus, vagy egy már definiált osztály. A Java primitív típusait a Táblázat 2 foglalja össze. Ha a változó primitív típusú, akkormagát az értéket tárolja, míg osztály típus esetén egy referenciát tárol az egyobjektumra, amelyen keresztül hivatkozhatunk az objektum adattagjaira, vagy
10 Először típusát majd - szóközzel elválasztva - nevét megadva
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 11/80
üzenetet küldhetünk neki. Ebből következően az értékadásoknál a primitív típusokérték szerint, míg az objektumok cím szerint adódnak át.
Primitív típus Leírás Kezdeti érték11
Boolean logikai típus falseChar 16 bites Unicode karakter A nullás kódú karakter
Byte 8 bites elő jeles egész 0
Short 16 bites elő jeles egész 0
Int 32 bites elő jeles egész 0
Long 64 bites elő jeles egész 0
Float 32 bites lebegő pontos szám 0.0
Double 64 bites lebegő pontos szám 0.0
Táblázat 2
A primitív típusú változók értékét operátorok, míg az objektumok értékétoperátorok és üzenetküldések segítségével manipulálhatjuk. A felhasználhatóoperatorokat a Táblázat 3 foglalja össze prioritásuknak megfelelően (csökkenő sorrend). Ezekkel a késő bbiekben foglalkozunk részletesebben. Az azonos prioritásiszinten álló operátorok többsége balról jobbra értékelődik ki, kivételt képeznek ezalól az értékadások. A kifejezésekben szereplő metódushívások (üzenetküldések) akiértékelésnek megfelelő sorrendben hajtódnak végre.
Operátor megnevezés
[] . (kif 12) kif++ kif-- postfix operátorok
++kif –kif +kif –kif ! ~ prefix operátorok
new (típus)kif példányosítás, típuskényszerítés
* / % multiplikatív operátorok
+ - additív operátorok
<< >> >>> léptető műveletek
< > <= >= instanceof összehasonlítások
== != egyenlőség-vizsgálatok
& bitenkénti ÉS
^ bitenkénti kizáró VAGY
| bitenkénti VAGY
11 Valamilyen osztály típussal rendelkező változó kezdeti értéke a null referencia12 A kif a kifejezés rövidítéseként szerepel
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 12/80
&& logikai ÉS
|| logikai VAGY
?: feltételes kifejezés
= += -= *= /= %= >>= <<= >>>= &=^= |=
értékadások
Táblázat 3
Az operátorokkal összekötött változókat és konstansokat kifejezésneknevezzük, míg a pontosvesszővel lezárt kifejezést utasításnak. A kifejezést arendszer kiértékeli, s az eredményt további felhasználásra visszaadja. Az utasításvégrehajtódik, nincs visszatérési értéke. Bárhol, ahol utasítást adhatunk meg,használhatunk blokkot is. A blokk kapcsos zárójelek közé zárt utasítások sorozata 13.
A Java er ősen típusos nyelv, így a fordító minden előforduló kifejezésbenleellenőrzi, hogy a megadott értékek megfelelő típusúak-e. Egy szűkebbértéktartományból tágabb értéktartományba átléphetünk, de ha ugyanezt visszafelé
próbáljuk, fordítási hibát kapunk. (Egy long típusú változó értékül kaphatja egy inttípusú változó értékét, de visszafele ez nem működik) A típuskényszerítés operátoráthasználva explicit konverziót hajthatunk végre, viszont ezt sem alkalmazhatjukminden esetben. (Egy logikai értéket például nem lehet közvetlenül számmákonvertálni, s egy szám sem fogható fel logikai értékként)
Kifejezések és utasítások:
- l ong l = 3. 0 Ez egy kifejezés, hiszen nem zárja pontosvessző. Azértéke kiértékelés után: 3.0
- i nt i = 4 + j ; Ez már utasítás.- i nt er t ek = ( i nt ) ( 9 / 4) ; Explicit típuskényszerítés egy
utasításban. (ertek == 2) Megj.: Ilyen esetekben a futtató környezetexplicit típuskényszerítés alkalmazása nélkül is elvégzi a konverziót.
- {i nt i = 3} Ez szintén utasítás, hiszen a blokképző zárójeleklezárják a szerkezetet, utasítássá alakítva ezáltal a kifejezést. Megj.:Az i változó értéke csak a blokkon belül érhető el
2.2. SzekvenciaA Java legegyszer ű bb vezérlési szerkezete a szekvencia, amely egymás után írt
utasításokat jelent. Err ől a vezérlési szerkezetr ől egyszer űsége és egyértelműségemiatt sokan megfeledkeznek, ezért nagyon fontos, hogy megemlítsük. Ilyen esetbenaz utasítások a leírásuknak megfelelő sorrendben hajtódnak végre, s egy utasításracsak akkor kerül a vezérlés, ha minden őt megelőző utasítás végrehajtódott. Azutasítások lezárására csak a ’;’ (pontosvessző) használható. Az új sor karakter, és azegyéb térköz karakterek sem zárják le az utasítást, viszont egy sorba több utasítás isírható. A Példa 2.1-ben felsorolt kódrészletek ugyanazt a szekvenciát jelentik.
13 Itt visszautalnék arra, hogy egy blokkon belül létrehozott változó csak a blokkon belül érhető el
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 13/80
Példa 2.1 Szekvenciák1. i nt i =5; i nt j =i ;
2. i nti=
5; i nt j= i ;
3. i nt i = 5;i nt j = i ;
Az olvashatóságot szem előtt tartva mégis az utolsó változat a javasolt.
2.3. Feltételes elágazások
A Java nyelv három módot ad feltételes vezérlésátadásra. Ezek közül az első, azoperátorok között már említett feltételes kifejezés. A nevéből adódóan ez egy
kifejezés, tehát kiértékelés után értéket ad vissza, további feldolgozásra.
A szintaktikája:
logikai kifejezés ? kifejezés1 : kifejezés2
A kifejezés kiértékelésének első lépésében kiértékelődik a logikai kifejezés,majd ennek igaz volta esetén a kifejezés1, hamis volta esetén pedig a kifejezés2 visszatérési értéke lesz a teljes feltételes kifejezés eredménye. Például a Példa 2.2 esetén, ha val t ozo értéke kisebb, mint 5, akkor a szoveg értéke „kicsi”, ellenkező esetben „nagy” lesz.
Példa 2.2 Feltételes kifejezésszoveg = val t ozo < 5 ? „ki csi ” : „nagy”;
Megj.: Természetesen a példából hiányoznak a változó-deklarációk, s mégnagyon sok egyéb ahhoz, hogy önálló fordítási, illetve futtatási egységet alkosson,ezért nem teljes, de remélem elég szemléletes.
A következő felhasználható feltételes elágazás az egyszeres elágazás, vagyismertebb nevén az if-then-else szerkezet. Ez tartalmilag annyiban különbözik afeltételes kifejezéstől, hogy utasításként viselkedik.
A szintaktikája:if( logikai kifejezés )
utasítás1 else
utasítás2
Ha a logikai kifejezés igazat ad vissza, akkor az utasítás1-re, míg hamisvisszatérési érték esetén az utasítás2-re kerül a vezérlés. A blokképző zárójelek ( a {valamint a } ) alkalmazásával több utasítást is megadhatunk. Az else ág elhagyható.Ezek után az egyszeres elágazást az elő bbi példánkra alkalmazva a következő
kódrészletet írhatjuk:
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 14/80
Példa 2.3 Feltételes elágazási f ( er t ek < 5) {
szoveg = „ki csi ”;} el se {
szoveg = „nagy”;
} Megj.: Természetesen a blokképző zárójelek ez esetben elhagyhatóak, hiszen
csak egy utasítást akarunk végrehajtani mindkét esetben.
Az összetett elágazás egymásba ágyazott kétágú elágazásokkal is megoldhatólenne, de a legtöbb programozási nyelvhez hasonlóan a Java-ban is használhatunkerre egy külön nyelvi elemet. Ez a switch szerkezet.
A szintaktikája:
switch( kifejezés ){case érték 1:case érték 2:. . .case érték n:default:
}
Az utasítás végrehajtásának első fázisában kiértékelődik a kifejezés, majdmegkezdődik a visszaadott értéknek a felsorolásban szereplő értékekkel történő egyeztetése. Egyezőséget találva a JVM végrehajtja az összes utána szereplő utasítást
(tehát nem áll meg a következő case ágnál, ellentétben a Pascal-lal, s összhangban aC/C++-szal) Ha a feldolgozás során nem talál egyező értéket, akkor a default ágbanmegadott utasítások kerülnek végrehajtásra. (A default ág elhagyható) Egy adottághoz bármennyi utasítás tartozhat. A kifejezés visszatérési értéke, valamint afelsorolt értékek csak egész számok lehetnek.
Példa 2.4 Összetett elágazásswi t ch( er t ek){
case 5:case 4: szoveg = „nem ”;case 3:case 2:case 1: szoveg += „ki s szám”;def aul t : szoveg = „Nem t udom”;
}
A Példa 2.4-ban a szoveg értéke az ertek változó nagyságától függően másés más. Ha az ertek értéke 5, vagy 4, akkor a szoveg értéke „nem ki s szám”,míg 4-nél kisebb pozitív egész esetén „ki s szám” lesz. Ha az ertek értéke 5-nélnagyobb, vagy nem pozitív, akkor a szoveg „Nem t udom” értéket veszi fel.
Megj.: A szoveg += „ki s szam” kifejezés egyenérték ű a szoveg =szoveg + „ki s szam” kifejezéssel.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 15/80
2.4. Iterációk
Bizonyos tevékenység(ek) ismétlődő végrehajtását iterációnak nevezzük. Avégrehajtandó tevékenységek alkotják a ciklusmagot. Az iterációt mindig kíséri egyfeltételvizsgálat, melynek eredményétől függ, hogy a következő ciklust kell
elvégezni, vagy kilépünk az iterációból. Általános gyakorlat, hogy a ciklusmagbanegy ciklusváltozót használunk fel, illetve annak értékét változtatjuk, s ugyanezt aváltozót a feltételben vizsgáljuk. A Java három különböző iterációt támogat: azelöltesztelőt, a hátultesztelőt, és a léptetőt. Mindhárom esetben belépési feltételt kellmegadnunk, tehát a feltételes kifejezés arról dönt, hogy végre kell e hajtani akövetkező ciklust.
Az elöltesztelő iteráció szintaktikája:
while( logikai kifejezés )utasítás
Ennél az iterációnál először kiértékelődik a logikai kifejezés, majd annak igazvisszatérése estén végrehajtódik az utasítás. Ha a logikai kifejezés kezdetben hamis,akkor az utasítás egyszer sem fog végrehajtódni.
A hátultesztelő iteráció szintaktikája:
doutasítás
while( logikai kifejezés )
A hátultesztelő iteráció használatakor először végrehajtódik az utasítás, majd alogikai kifejezés visszatérési értékétől függően egy újabb ciklus indul, vagyelhagyjuk az iterációs szerkezetet. Ennek a végrehajtási módnak köszönhetően aciklusmag legalább egyszer minden esetben lefut.
A léptető iteráció szintaktikája:
for(ciklusváltozó = kezdeti érték; logikai kifejezés; ciklusváltozó léptetése)utasítás
A léptető iteráció használatakor szükség van egy ciklusváltozóra, amely az első ciklusmag-végrehajtás előtt kezdeti értéket kap. Minden ciklusmag-végrehajtás előtt
kiértékelődik a logikai kifejezés, s az utasításra csak akkor kerül a vezérlés, ha avisszatérési értéke igaz. Az ut asítás végrehajtása után megtörténik a ciklusváltozóléptetése, majd újra a logikai kifejezés kiértékelése következik. Egy iterációfejlécében több ciklusváltozó is megadható, egymástól vesszővel elválasztva.Ugyanezen módon többszörözhetőek a logikai kifejezések és a ciklusváltozó léptetéseis. A logikai kifejezések többszörözése esetén közöttük logikai ÉS kapcsolat áll fenn,így csak akkor lépünk a következő ciklusba, ha minden kifejezés visszaadott értékeigaz.
Megj.: A többszörözés itt azt jelenti. hogy akár nulla darab is megadható
bármely fejlécrészből.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 16/80
Az iterációs formák között biztosított az átjárás, tehát bármely iterációátalakítható bármely más iterációvá, így csak az adott feladat jellege, s a
programozói döntés határozza meg, hogy mikor melyiket érdemes használni. Azátjárásra mutat példát a Példa 2.5, bevezetve a következő jelöléseket14:
- CK: Ciklusváltozó kezdőértékének beállítása- LK: Logikai kifejezés- CM: Ciklusmag (az elvégzendő tevékenység)- CL: Ciklusváltozó léptetése
Példa 2.5 Iterációk közötti átjárás1. Elöltesztelő iteráció:
CK;while(LK){
CM;CL;
}2. Hátultesztelő iteráció:
CK;do{
CM;CL;
} while(LK);
3. Léptető iterációfor(CK; LK; CL) CM;
Alkalmazzuk a Példa 2.5-t egy valós problémára. A feladat: Ki kell írni az első tíz természetes számot (0..9) a képernyőre. A megoldás a Példa 2.6-on látható.- CK: i nt i = 0; - LK: i < 10 - CM: System. out . pr i nt l n( i ) ; - CL: i ++;
Példa 2.6 Természetes számok kiírása a képernyő re különböző iterációk használatával1. Elöltesztelő iteráció:
i nt i = 0;whi l e( i < 10) {
Syst em. out . pr i nt l n( i ) ; i ++;}
2. Hátultesztelő iteráció:i nt i = 0;do{
Syst em. out . pr i nt l n( i ) ; i ++;} whi l e( i < 10) ;
3. Léptető iterációf or ( i nt i =0; i <10; i ++) Syst em. out . pr i nt l n( i ) ;
14 Légrádi Gábor ajánlása nyomán
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 17/80
2.5. Feltétel nélküli vezérlésátadás
Az eddig tárgyalt vezérlési szerkezetek mindegyikében szerepelt egy logikaikifejezés, amellyel eldönthettük, hogy kettő, vagy több lehetséges út közül melyiketválassza a futtató rendszer. A vezérlési szerkezetek másik nagy csoportját azok a
lehetőségek alkotják, ahol nincs logikai kifejezés; minden ellenőrzés nélkül átkerül avezérlés egy másik, (a szekvenciának nem megfelelő) utasításra.
A legáltalánosabb feltétel nélküli vezérlésátadást biztosító kulcsszavak a break és a continue. A break az adott vezérlési szerkezet elhagyását biztosítja, tehát átadjaa vezérlést az befoglaló elágazás, vagy iteráció után következő első utasításra. Alegf ő bb felhasználási területe a switch szerkezet, ahol a break használatávalelérhetjük, hogy csak az adott értékhez tartozó utasítássor fusson le (Példa 2.7).
Példa 2.7 break utasítás használata switch szerkezetben
swi t ch( er t ek){case 2: Syst em. out . pr i nt l n( „Ez a szám a ket t ő” ) ;br eak;
case 1: Syst em. out . pr i nt l n( „Ez a szám az egy”) ;br eak;
case 0: Syst em. out . pr i nt l n( „Ez a szám a nul l a”) ;br eak;
def aul t : Syst em. out . pr i nt l n( „Nem i smer em a számot ”) ;}
A break-kel szemben a continue nem a vezérlési szerkezetet, hanem csak egyutasításblokkot hagy el, így például elérhető a léptető iteráció bizonyos ciklusainak,ciklusmag-részleteinek átugrása. A break és continue közötti különbséget a Példa 2.8 szemlélteti.
Példa 2.8 A break és continue közötti különbségf or ( i nt i =0; i <10; i ++) {
i f ( i ==5) br eak;Syst em. out . pr i nt l n( „Az i ér t éke: ” + i ) ;
}f or ( i nt i =0; i <10; i ++) {
i f ( i ==5) cont i nue;
Syst em. out . pr i nt l n( „Az i ér t éke: ” + i ) ;}
Az első léptető iteráció esetében a számok 0-tól négyig íródnak ki, hiszen a break hatására elhagyjuk az iterációt, míg a második esetben csak átugorjuk az 5-összám kiírását, így 0-tól 4-ig, illetve 6-tól 9-ig minden szám meg fog jelenni aképernyőn.
A break és a continue is használható egy címké vel együtt. A címke egyiterációt, vagy egy programblokkot jelölhet. Használatának hatása, hogy a break azutána megadott címkével ellátott iterációt hagyja el, illetve a continue a címkével
azonosított programblokkból lép ki.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 18/80
A címke elhelyezésének szintaktikája:
cimke:{ }vagy cimke: vezérlési szerkezet...
, ahol a cimke felírat helyett a programblokk, vagy a vezérlési szerkezetazonosítására használni kívánt azonosítót kell megadni. A címkét a feltétel nélkülivezérlésátadásokkal úgy használhatjuk együtt, hogy a break vagy a continue kulcsszóután megadjuk, hogy melyik címkével ellátott blokkra vonatkozik. Ezzel megoldható
például egymásba ágyazott iterációk, vagy blokkok közül a külső szerkezetelhagyása (Példa 2.9)
Példa 2.9 Cimke használatakul so: f or ( i nt i =0; i <10; i ++)
f or ( i nt j =10; j >0; j - - ) {. . .i f ( i ==j ) br eak kul so;. . .
}egyi k: whi l e( ! f al se) {
. . .{
. . .i f ( val t ! = 18) cont i nue egyi k;. . .
}}
A harmadik feltétel nélküli vezérlésátadó utasítás a return. Ennek használatávalegy metódust hagyhatunk el, illetve adhatjuk meg visszatérési értékét, de err őlrészletesebben majd a metódusok használatánál.
3. OOP a Java-ban15
A Java-ban, mint már megállapítottuk, nincs objektumokon kívüli programozás. Nincsenek a klasszikus értelemben vett függvények és eljárások. Csak objektumokvannak, s hozzájuk tartozó adattagok és metódusok. A problémát nem egymásthívogató függvényekkel, hanem egymással együttműködő, egymássalüzenetváltásokon keresztül érintkező objektumokkal oldhatjuk meg.
Objektumot egy osztály példányosításával hozhatunk létre. Ha nincskívánalmainknak megfelelő osztály, akkor nekünk kell létrehozni azt egyosztálydeklaráció segítségével. Ennek a lehetőségeir ől és módjairól szól ez a fejezet.Osztálydeklarációt a class kulcsszóval, majd egy azonosító megadásával hozhatunklétre, blokkképző zárójelek közé zárva az osztály adattagjait és metódusait leírókódrészleteket. Erre a definiálásra láthattunk példát a Példa 1.2-ben, amely egyosztálydefiníció hozzáadott adattagok és metódusok nélkül, illetve a Példa 1.3-ban,ahol az osztályhoz megadtunk egy metódust is.
15 Az osztályok terveinek megadásakor az UML jelöléseit használjuk
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 19/80
3.1. Adattagok, metódusok
Az objektumok tulajdonságait adattagok reprezentálják. Egy adattagnak mindigvan egy típusa (amely lehet primitív típus, vagy osztály típus) és egy azonosítója(neve). Az adattagok a típusuknak megfelelő értékek tárolására szolgálnak, de
értéküket az objektum életciklusa során megváltoztathatják. Az adattagok értékeinekkombinációja alkotja az objektum aktuális állapotát. Egy adattag mindig egyobjektumhoz tartozik, ezért az objektum osztályának definíciójában típusának ésértékének párosával adhatjuk meg. A Példa 3.1-ben az Alkalmazott osztályadattagjainak definícióját láthatjuk. Az osztály tartalmaz egy primitív típusú (egészszám) fizetes adattagot, illetve egy osztály típusú (karaktersorozat) nev adattagot.
Példa 3.1 Adattagok létrehozásacl ass Al kal mazot t {
i nt f i zet es;St r i ng nev;
}
Az adattagokhoz kezdeti értéket rendelhetünk az értékadás operátorainaksegítségével, amelyben felhasználhatjuk a már korábban meghatározott adattagokat.(Példa 3.2) Ha nem adunk meg kezdőértéket, akkor a Java rendszer automatikusanmeghatároz egyet, amelyek értékét a Táblázat 2 tartalmazza. Az osztály típusúadattagok alapértelmezett értéke az úgynevezett null referencia, amely egy nemlétező memóriacímet jelent. A tömörebb kódok elérése miatt megengedett, hogy egyadattag-deklaráción belül több azonos típusú adattagot is megadjunk, jelölve a típust,majd az egymástól vesszővel elválasztott a neveket (Példa 3.2)
Példa 3.2 Adattagok ellátása kezd ő értékkelcl ass Al kal mazot t {
St r i ng nev;i nt f i zet es = 50000, l evonasok = f i zet es/ 4;
}
Az osztályokhoz tartozó objektumok viselkedését (más megfogalmazásban azobjektumokhoz küldhető üzeneteket) az osztály definíciójában felsorolt metódusokhatározzák meg. A Java nyelv keretein belül a metódusoknak két nagy csoportjátkülönböztethetjük meg a visszatérési értéknek megfelelően. Az egyik csoportban a
visszatérési értékkel nem rendelkezőket, míg a másik csoportba a visszatérésiértékkel rendelkezőket sorolhatjuk. A visszatérési értékkel rendelkező metódusokesetén meg kell adni az érték típusát, míg a másik csoport esetén a void kulcsszóhelyettesíti azt. Ezeket a gondolatokat szem előtt tartva egy metódust úgy hozhatunklétre, hogy megadjuk a visszatérési típust (vagy ha az nincs, akkor a void kulcsszót),majd megadjuk a metódus nevét. A nevet egy zárójelpár követi, amelyben vesszővelelválasztva megadhatóak a paraméterek (típus és név párossal). Az ily módonmegadott metódus-fejlécet16 (szignatúra) egy kapcsos zárójelek közé zárt metódus-deklaráció követi.
16 Természetesen más módosítók és kulcsszavak is megadhatók a metódus fejlécében, ezekr ől viszont csakkéső bb esik szó
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 20/80
Egy metódust a neve és a paraméterlistája azonosít egyértelműen, tehát egyosztályon belül megadható két azonos nevű metódus, ha azok paraméterlistája vagy alistában szereplő paraméterek típusaiban, vagy azok sorrendjében, esetleg mind akettő ben eltér. Hivatkozáskor a futtató környezet a megadott paraméterek típusábólés sorrendjéből el tudja dönteni, hogy a két azonos nevű metódus körül melyiket kellvégrehajtania. Az így létrehozott szerkezetet a polimorfizmus egyik formájánaktekinthetjük (metódusok polimorfizmusa).
A metódusok fajtáinak alkalmazási lehetőségeit a Példa 3.3-n követhetjükvégig. Visszatérési értékkel nem rendelkező metódus a fizetestEmel paraméteres és
paraméter nélküli változata. Ez a metóduspár egyben a polimozfizmusra is példa. AgetNev metódus a visszatérési értékkel rendelkező metódusok közé sorolható. Ittláthatjuk, hogy a visszatérési értéket a return feltétel nélküli vezérlésátadó utasítássalhatározhatjuk meg, ahol a kulcsszó után meg kell adni a visszatérési értéket. A returnkulcsszó után megadott érték, adattag vagy változó típusának meg kell egyeznie ametódus fejlécében megadott típussal. A setNev egy visszatérési érték nélkülimetódus, amelyben egy névazonosságot feloldó lehetőség található. Ha egymetódusban olyan változó-, vagy paraméternevet alkalmazunk, amely egyben azosztály egy adattagjának is az azonosítója, akkor a this kulcsszóval minősítvehivatkozhatunk az adattagra, míg minősítés nélkül a paraméterre (lokális változóra).
Példa 3.3 Adattagok és metódusokcl ass Al kal mazot t {
i nt f i zet es = 50000;St r i ng nev;
voi d f i zet est Emel ( ) {f i zet es += 5000;
}voi d f i zetest Emel ( i nt novekmeny){
f i zet es += novekmeny;}St r i ng get Nev( ) {
r et ur n nev;}voi d setNev(St r i ng nev){
t hi s. nev = nev;}i nt get Fi zet es( ) {
r et urn f i zet es;}voi d set Fi zet es( i nt f i z){
i f ( f i zet es > f i z) ret urn;f i zet es = f i z;
}}
Megj.: Az adattagok és metódusok sorrendje nem kötött, de ha szétválasztjukőket, akkor áttekinthető bb, olvashatóbb kódhoz jutunk.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 21/80
3.2. Konstruktor, objektum létrehozása
Egy osztály példányosítása mindig valamelyik konstruktorának segítségéveltörténhet meg. A konstruktor az objektum életciklusa alatt pontosan egyszer fut le,létrehozva ezzel az objektumot, s beállítva az adattagjainak kezdeti értékét. A
konstruktor lefutása után az objektum kész az üzenetek fogadására, feladatánakelvégzésére. A konstruktor neve kötött (mindig megegyezik az őt hordozó osztálynevével), így egy osztálynak csak akkor lehet több konstruktora, ha azok ametódusoknál említett módon eltér ő paraméterlistával rendelkeznek. A konstruktoregy speciális metódusként fogható fel, amelyet úgy is értelmezhetünk, hogy egymetódus, amelyiknek neve megegyezik az osztály nevével, s nincs visszatérési értéke(még void sem), vagy úgy, hogy az osztály típusával visszatér ő névtelen metódus.
Egy osztályhoz mindig tartoznia kell legalább egy konstruktornak, hiszen enélkül az osztály nem példányosítható, nem hozhatók létre az osztály típusát viselő
objektumok. Ha nem adunk meg konstruktort, akkor a fordító rendszer mindiglétrehoz egy alapértelmezett, paraméter nélküli konstruktort.
Konstruktorok létrehozásának módját a Példa 3.4-n követhetjük végig. Itt ishasználható a this kulcsszó, amelynek egy újabb alkalmazási lehetőségét mutatja amásodik konstruktorunk. Itt a this az aktuális osztály egy másik konstruktoránakhívását jelenti.
Példa 3.4 Konstruktorok létrehozásacl ass Al kal mazot t {
i nt f i zet es;St r i ng nev;
Al kal mazot t ( ) {nev = „I smer et l en”;f i zetes = 50000;
}Al kal mazot t ( St r i ng nev){
t hi s( nev, 50000) ;}Al kal mazot t ( St r i ng nev, i nt f i zet es) {
t hi s. nev = nev;t hi s . f i zet es = f i zet es;
}. . .
}
Osztályok példányosítására a new operátor használható, amelynek meg kelladni, hogy melyik konstruktort hívjuk meg, s milyen paraméterekkel. (Példa 3.5)
Példa 3.5 Objektumok példányosításaAl kal mazot t a;a = new Al kal mazot t ( „Ki ss Bél a”) ;
vagy,Al kal mazot t a = new Al kal mazot t ( „Ki ss Bél a”, 92000) ;
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 22/80
3.3. Öröklés, láthatósági szintek
„Már 12 éve rendszeres repülő járatok közlekedtek az Atlanti-óceán felett,amikor Irwin Arkwrite úri szabó és feltaláló saját készítésű madáremberfelszerelésében levetette magát az Eiffel-torony tetejér ől. 6 másodperc múlva már
lenn is volt. Kísérletező kedv híján számos találmánnyal lenne szegényebb azemberiség. De az olyan problémák esetében, amelyek kezelésére van biztos módszer,kár fáradozni.”
Synergon reklám
A OO programok újrahasznosításának legkézenfekvő bb módja az öröklés,amelynek elméletér ől már ejtettünk néhány szót az 1.6.3 fejezetben. A Java csak azegyszeres öröklést támogatja, amelynek hatékonysági okai vannak. Így gyorsabb ésmegbízhatóbb programokat írhatunk, csökkenthetjük a hibalehetőségeket. Bárhol,ahol a fordító vagy futtató rendszer egy bizonyos osztály valamely objektumát
igényli, megadható az igényelt osztály egy leszármazottja is, hiszen az öröklésimechanizmusnak köszönhetően biztosított, hogy a leszármazott osztály mindenüzenetre tud reagálni, amelyre őse is tudna.
Ha err ől másként nem rendelkezünk, akkor az újonnan létrehozott osztályunkaz őse az Object nevű lesz, ezzel egy közös őst deklarálva az összes Java-banelőforduló osztálynak. Ezt kihasználva olyan általános programokat írhatunk, amelynem köti ki, hogy egy adott milyen osztályú objektumra van szükségünk, csak arrólrendelkezik, hogy objektumra van szükségünk. (Erre jó példa a verem adatszerkezet,amelynek leírásakor nem kell megadni, hogy milyen típusú objektumokat szeretnénk
tárolni, pontosabb az Object osztályt adjuk meg, így az alkalmazás során bármilyenobjektum tárolható a veremben)
Ha osztályunk számára nem megfelelő az Object osztályból történő származtatás, akkor az extends kulcsszót használva más ősosztályt definiálhatunk.Ekkor az újonnan létrejövő osztályunk használhatja az ősosztály metódusait, illetveújabbakkal egészítheti ki vagy, felüldefiniálhatja (más implementációt megadva)azokat. (Példa 3.6)
Példa 3.6 Leszármaztatáscl ass Fonok ext ends Al kal mazot t {
i nt nyel vekSzama;Fonok( St r i ng nev, i nt f i zet es, i nt nyel vek) {
super ( nev, f i zet es) ;nyel vekSzama = nyel vek;
}i nt get Fi zet es( ) {
r etur n f i zet es + nyel vekSzama*3000;}i nt addNyel v( ) {
nyel vekSzama++;
}}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 23/80
Az öröklés során az adattagok és a metódusok kerülnek át a leszármazottosztályba, tehát a konstruktorok nem. Van viszont lehetőség arra, hogy az ős osztályegy konstruktorát meghívjuk a leszármazott osztály konstruktorából. Ez a lehetőség asuper kulcsszó segítségével érhető el. A super egy hivatkozás az ős osztályra,működése a this kulcsszóhoz hasonlatos. Segítségével hivatkozhatunk konstruktorra,vagy az ős osztály egy felüldefiniált metódusára (super.getFizetes()) Ha nem írunkkonstruktort, akkor a fordító automatikusan beilleszt egy paraméter nélkülit,amelynek első sora a super() konstruktorhivatkozás. Ezért ha az ős osztályunk nemrendelkezik paraméter nélküli konstruktorral, hibaüzenetet kapunk. Ilyen esetbenírnunk kell egy konstruktort, amelyben meg kell adnunk, hogy melyik őskonstruktortszeretnénk használni, s milyen paraméterekkel.
A Java az adatelrejtés (1.6.2) megvalósítására négy láthatósági szintet biztosít.Ezekkel a láthatósági szintekkel szabályozhatjuk, hogy egy megfelelő kulcsszóvalmegjelölt adattaghoz, metódushoz, vagy konstruktorhoz ki férhet hozzá. Ahasználható szinteket, s azok láthatóságát a Táblázat 4 tartalmazza. (A félnyilvánosláthatósági szint az alapértelmezett. Ebben az esetben nem kell kulcsszót használni.)
Befoglalóosztály
Azonos csomag17 Leszármazottosztály
Egyébosztály
private X - - -
félnyilvános X X - -
protected X X X -
public X X X X
Táblázat 4
A láthatósági szinteket kihasználva az adatelrejtést úgy valósíthatjuk meg, hogyaz adattagokat private-ként deklaráljuk, s public módosítóval ellátott metódusokatdeklarálunk hozzá, amelyek szolgáltatják az adattag értékét, vagy ellenőrzés után
beállítják az új értéket. (Példa 3.7)
Példa 3.7 Adatelrejtés láthatósági szintek használatávalpubl i c cl ass Al kal mazot t {
pr i vat e i nt f i zet es ;. . .publ i c i nt get Fi zet es( ) {
r et urn f i zet es;}publ i c i nt set Fi zet es( i nt uj Fi zet es){
i f ( uj Fi zet es > f i zet es)f i zet es = uj Fi zet es;
}. . .
}
17 A csomag fogalmát a 4.1 fejezetben vezetjük be
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 24/80
3.4. A tervezés és a megvalósítás szétválasztása
Sokszor szükség lehet arra, hogy egy adott ős osztályban ne adjuk meg egyvagy több metódus deklarációs részét, csak jelöljük, hogy az ebből az osztálybólszármazó osztályoknak tartalmazniuk kell ezt a lehetőséget, tudniuk kell válaszolni
egy ilyen üzenetre. Erre akkor lehet szükség, ha egy adott ősosztály definiálásakormég nem tudjuk, hogy hogyan fogjuk megvalósítani, vagy másokkal megvalósíttatniezt a megjelölt metódust, csak egy egységes interfészt akarunk létrehozni, amelyetily módon több helyütt is felhasználhatunk. Erre a problémára a Java bevezette azabstract módosítót, amelyeket metódusok fejlécében használhatunk. (példa) Ha egyosztálydefiníció tartalmaz legalább egy abstract módosítóval ellátott metódust, akkoraz osztályunk fejlécét is el kell látni az abstract kulcsszóval. Az absztrakt osztályoknem példányosíthatóak, viszont felhasználhatóak más osztályok őseként, aleszármazottra bízva a metódus(ok) implementálását (megvalósítását) Az abstractmódosítóval ellátott metódusoknak nincs törzs részük, a fejlécet egy pontosvessző
zárja. Egy példa absztrakt metódusra:publ i c abst r act voi d hel yet Val t ( ) ;
A csak absztrakt metódusokat (és konstansokat) tartalmazó osztályok helyetthasználhatjuk az interface kulcsszót, amely egy igen hatékony eszközt ad a
programozók és rendszerfejlesztők kezébe. Mivel az interface nem tartalmazmetódus-törzseket, a többszörös öröklésnél nem léphet fel névütközés, ezért ez alehetőség itt megengedett. Ily módon a Java-n belül az interfészek használatávalszimulálható a többszörös öröklés (ez néhány esetben elkerülhetetlen)
publ i c i nt er f ace Ki r ughat o{
publ i c voi d ki r ug( ) ;}
Az interface önálló fordítási egység, elnevezéseire ugyanazok a szabályokvonatkoznak, amik a class-ra. (Az interface neve és az őt tartalmazó file nevemegegyezik.) Bárhol használhatunk interfésztípust, ahol osztálytípus megadható(adattag típusaként, metódusok paraméterlistájában, típuskényszerítéshez ...)
Az interfészek egyik felhasználási lehetősége, ha belőle származtatva újabbinterfész(eke)t hozunk létre, felhasználva a már meglévő metódusdeklarációkat éskonstansokat, a másik pedig, hogy egy osztály definíciójában megadjuk, hogyszeretnénk implementálni ezt az adott interfészt. Az első lehetőség alkalmazásáhozugyanúgy kell eljárni, mint az osztályok öröklésénél (extends kulcsszó, detöbbszörös öröklés is létrehozható, egymástól vesszővel elválasztott interfésznevekfelsorolásával).A második lehetőség kiaknázásához alkalmaznunk kell az implements kulcsszót. Ezt a kulcsszót az osztálydefiníció fejlécébe kell elhelyezni, utánamegadva (egymástól vesszővel elválasztva) az implementálni kívánt interfészeket.Ha egy osztály implementál néhány interfészt, akkor vagy meg kell adni azinterfészekben szereplő összes metódus egy megvalósítását (implementációját), vagyaz osztályt absztraktként (abstract) kell definiálni, s a leszármazottaiban kellgondoskodnunk arról, minden meghatározott metódushoz tartozzon egy kódsorozat(Példa 3.8)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 25/80
Példa 3.8 Interfész implementálásapubl i c cl ass Al kal mazot t i mpl ement s Ki r ughat o{
. . .publ i c voi d ki r ug( ) {
f i zet es = 0;
Syst em. out . pr i nt l n( nev + „ szomor ú”) ;}. . .
}
3.5. Osztály szintű adatok, metódusok, konstansok, inicializátorok
Eddig objektum szintű adattagokat használtunk. Ezek az adattagok mindenobjektumhoz letárolódnak, minden létrehozott objektum rendelkezik egy-egy ilyenadattaggal, azt tetszés szerint változtathatja, ez a változás nincs kihatással a többiobjektumra. A redundancia elkerüléséhez azonban néha szükséges, hogy egy adott
adattagot ne objektum-, hanem osztály szinten deklaráljunk. Az ilyen adattagok csakegyszer tárolódnak le, ezért kevesebb helyet foglalnak, valamint ha egy objektummegváltoztatja az értékét, azt a változtatást a többi, vele azonos típushoz tartozóobjektum (illetve azok leszármazottjai) is érzékeli. Ily módon egyetlen utasítással azösszes azonos típushoz tartozó objektum állapotát változtathatjuk. Osztály szintű adattagok létrehozásához a static módosítót kell használnunk. Ez a lehetőségkiválóan alkalmas (sok más mellett) egyéni azonosítók létrehozására. (Példa 3.9)
A static kulcsszót használhatjuk metódusok megjelölésére is. Ekkor osztályszintű metódust hozunk létre, amelynek előnye, hogy nem kell az adott objektumot
példányosítani ahhoz, hogy szolgáltatását használhassuk 18
. A statikus metódusokcsak statikus adattagokhoz és saját változóihoz férhetnek hozzá. Az osztály szintű adattagok, és metódusok elérése szintén minősített hivatkozással történhet, ahol aminősítő lehet egy objektum, de akár az osztály neve is. Például a Példa 3.5-ben azAlkalmazott osztály Példa 3.9-ben létrehozott get Next I D( ) metódusárahivatkozhatunk az a. get Next I D( ) illetve az Al kal mazot t . get Next I D( ) segítségével is, mindkét esetben ugyanazt az eredményt kell kapnunk.
Példa 3.9 Osztály szint ű adattag és metódus használatapubl i c cl ass Al kal mazot t i mpl ement s Ki r ughat o{
. . .pr i vat e stat i c i nt next I D;pr i vat e i nt I D = next I D++;. . .publ i c i nt get I D( ) {
r et ur n I D;}publ i c st at i c i nt get Next I D( ) {
r et ur n next I D;}
}
18 Ilyen osztály szintű metódus a futtatható kódok main metódusa
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 26/80
Konstansok létrehozására a final módosítót használhatjuk, amellyel egyadattagot ellátva elérhető, hogy az adott adattag értékét ne változtathassa senki (mégaz az objektum, vagy osztály sem, amely tartalmazza) A final kulcsszóval ellátottadattag csak egyszer kaphat értéket, tehát az objektum életciklusa alatt csak egyszerállhat értékadás bal oldalán. Ahhoz, hogy az egyszeri értékadás biztosított legyen,vagy a konstruktorban kell szerepelnie (hiszen ez minden objektum életében csakegyszer fut le), vagy az adattag definiálásakor adhatjuk meg a kezdőértéket, amelyezután megváltoztathatatlan (Példa 3.10) Természetesen az osztály típusú adattagokállapota megváltoztatható, csak az értékadás tiltott. A final kulcsszó osztály szintű adattagok előtt is használható, így hozva létre mindenkire érvényes konstansokat.(Példa 3.11) Az osztály szintű konstansok esetén nem biztosított a konstruktoregyszeri lefutása, így az ilyen adattagoknak csak a deklaráció során adhatunk értéket.
Példa 3.10 Objektum szint ű konstanspubl i c cl ass Al kal mazot t i mpl ement s Ki r ughat o{
. . .pr i vat e f i nal i nt I D = next I D++;. . .
}
Példa 3.11 Osztály szint ű konstans létrehozásapubl i c cl ass Fonok extends Al kal mazot t {
pr i vat e st at i c f i nal NYELVPOTLEK = 3000;. . .publ i c i nt get Fi zet es( ) {
r et urn f i zet es + nyel vekSzama*NYELVPOTLEK;}
}A final kulcsszót használhatjuk metódus fejlécében, illetve osztálydeklaráció
fejlécében is. Metódusoknál ezzel érhetjük el, hogy az adott metódust ne lehessenöröklés során felüldefiniálni. Ilyen például az Object osztály getClass() metódusa,amellyel egy adott objektum osztályát tudhatjuk meg. A final módosítóval ellátottosztály az öröklési fa levél elemét jelöli, tehát nem szerepelhet más osztályokőseként. Erre példa a String vagy a System osztály.
Az utolsó nyelvi lehetőség, amelyet az OO kapcsán meg kell említeni azinicializátorok lehetősége. Ezek olyan programblokkok, amelyek nem tartoznakegyetlen metódushoz sem, s mindig a konstruktorok előtt futnak le. Ilyeninicializátort bárhol elhelyezhetünk az adattagok és metódusok deklarációi között.Az objektum szintű inicializátort a blokképző zárójelek közé zárva jelölhetjük, mígegy ilyen blokkot a static módosítóval ellátva egy olyan inicializátor hozható létre,amely az osztályra történő első hivatkozáskor aktivizálódik. („Osztály konstruktora”)Az Példa 3.12-vel az osztály szintű nextID adattagnak adhatunk egy kezdőértéket.
Példa 3.12 Statikus inicializátorpubl i c cl ass Al kal mazot t i mpl ement s Ki r ughat o{
stat i c{next I D = 1000;
}}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 27/80
3.6. Egy összetettebb példa
A feladat az Ábra 3-1-en látható UML diagrammal megadott osztályszerkezetmegvalósítása. A metódusok végleges megvalósításában egy szöveg képernyőreírásával követhetjük nyomon, hogy éppen milyen üzenetre válaszolunk.
Állat
populáció : int
getAllatPopulacio()helyetVáltoztat()
Emlő s
labakSzáma : int
getLábakSzáma() : intsetLábakSzáma(labSzám : int)megy()
Madár
tojástRak()Repülő
repül()
Tigris
BENGÁLI : int = 1KARDFOGÚ : int = 2alfaj : int
getAl faj() : int
Ember
név : String = "nincs"
beszél()getNev() : StringsetNev(név : String)
Superman
getSuperman() : SupermangolyótMegállít()
FecskeStrucc
Ábra 3-1 Osztálydiagram egy összetett példához
Az osztályok megvalósítását fentr ől lefele haladva készítjük el, tehát első megvalósítandó osztályunk az Allat.
Példa 3.13 Allat.javapubl i c abst r act cl ass Al l at {
pr ot ected st at i c i nt popul aci o;publ i c st at i c f i nal i nt get Al l at Popul aci o( ) {
r et ur n popul aci o;}publ i c abst r act voi d hel yet Val t ozt at ( ) ;
}
Az Allat osztály abstract, hiszen a hel yet Val t ozt at ( ) metódusa is abstract.Ennek oka, hogy egy Allat típusú objektumnál még nem tudjuk eldönteni, hogy
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 28/80
milyen módszereket alkalmaz a helyváltoztatásra. A populáció egy osztály szintű, protected minősítésű adattag, így annak változása minden leszármazott számáralátható, ily módon alkalmas a rendszerbe felvett Allat típusú objektumok számánaknyilvántartására. A protected kulcsszóra azért van szükség, hogy a leszármazottaktudják változtatni az értékét, más típusú objektum viszont ne. A final módosítóvalellátott get Al l at Popul aci o( ) metódus véglegesítését az indokolja, hogy ezzel amódszerrel elkerülhetővé tehetjük, hogy valamely leszármazottban (akár véletlenül)felüldefiniáljuk ezt a metódust, rossz eredményt szolgáltatva ezzel a felhasználó
programnak.
A következő megvalósítandó fordítási egység a Repulo interfész, hiszen ez nemfügg egyetlen más osztálytól, vagy interfésztől sem.
Példa 3.14 Repulo.javapubl i c i nt er f ace Repul o{
publ i c voi d r epul ( ) ;}
Az interfész egyetlen megvalósítandó metódus deklarál, ez a r epul ( ) . Azinterfészek csak publikus metódusokat és konstansokat deklarálhatnak, így aláthatósági szintet nem kötelező jelölni, de a nyomonkövethetőség miatt ajánlott.
Most már készen állunk arra, hogy megvalósítsuk a Madar osztályunk leírását,amely egy absztrakt osztály lesz, hiszen nem adunk implementációt a Repulointerfészből örökölt repul() metódushoz. A helyváltoztatáshoz a Madar osztályobjektumai a repülést használják.
Példa 3.15 Madar.javapubl i c abst r act cl ass Madar ext ends Al l at i mpl ement s Repul o{
publ i c voi d hel yet Val t ozt at ( ) {repul ( ) ;
}publ i c voi d t oj ast Rak( ) {
Syst em. out . pr i nt l n( „Egy ” + get Cl ass( )+ „ t oj ast r ak”) ;
}}
A tojastRak() üzenetre egy szöveg képernyőre írásával válaszol a Madar,amelyben szerepel az Object osztályból örökölt getClass() metódus. Ez a metódus azaktuális objektum osztályát adja meg.
Ha elkészült és lefordult a Madar osztályunk deklarációja, akkor minden adott aFecske illetve a Strucc osztályok elkészítéséhez. Ezek az osztályok már nemabsztrakt osztályok, tehát példányosíthatóak lesznek. A példányosítás érdekébenszükségünk van konstruktorra, amelynek minden egyes meghívása növeli a
populáció számát. Ezeknek az osztályoknak implementációt kell adniuk mindenegyes ős osztályuk olyan absztrakt metódusára, amit az eddigiek nem valósítottak
meg. Ennek a feltételnek a repul() metódus felel meg, így ez fellelhető mindkétosztályban.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 29/80
Példa 3.16 Fecske.javapubl i c cl ass Fecske ext ends Madar{
publ i c Fecske( ) {Syst em. out . pr i nt l n( „Ki kel t egy f ecske”) ;popul aci o++;
}publ i c voi d r epul ( ) {Syst em. out . pr i nt l n( „A f ecske gyor san r epul ”) ;
}}
Példa 3.17 Strucc.javapubl i c cl ass St r ucc ext ends Madar {
publ i c St r ucc( ) {Syst em. out . pr i nt l n( „Ki kel t egy st r ucc”) ;popul aci o++;
}publ i c voi d r epul ( ) {
Syst em. out . pr i nt l n( „A st r ucc nem t ud r epul ni ,ezer t i nkabb set al egyet ”) ;
}}
Több objektum nincs a madarak oldalán, így elkezdhetjük az emlősökdiagramrészletét. Szintén felülr ől lefelé építkezve az Emlos absztrakt osztállyalkezdjük. Az Emlos osztály (a nevén kívül) abban különbözik a Madar osztálytól,hogy a helyváltoztatást nem a repüléssel oldja meg, hanem definiál egy megy()metódust, amely ezen a szinten absztrakt. Emellett van egy plusz adattag azobjektum lábszámának nyilvántartására, amelyet egy metódus segítségévelkérdezhetünk le. A lábak számának beállítása egy új értékre csak akkor történik meg,ha az új érték kisebb, mint az eddigi érték. Vizsgáljuk azt is (ezek okait az olvasóra
bízva), hogy az új lábszám ne legyen negatív.
Példa 3.18 Emlos.javapubl i c abst r act cl ass Eml os ext ends Al l at {
pr ot ect ed i nt l abakSzama;publ i c i nt getLabakSzama( ) {
r etur n l abakSzama;}
publ i c voi d set LabakSzama( i nt uj Labszam) {i f ( ( uj Labszam < l abakSzama) | | ( uj Labszam < 0) ) {
Syst em. out . pr i nt l n( „Ez a( z) ” + get Cl ass( ) +„el veszt et t ” + ( l abakSzama- uj Labszam) +„ db l abat ”) ;
l abakSzama = uj Labszam;}
}publ i c voi d hel yet Val t ozt at ( ) {
megy( ) ;}publ i c abst r act voi d megy( ) ;
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 30/80
A következő osztályunk a Tigris, amely két konstanst tartalmaz, ezekkelazonosítva az alfaját. Két tigris-alfajt különböztetünk meg, a bengálit és a kardfogút.A tigris születésekor (konstruktor) meg lehet adni, hogy melyik alfajhoz tartozik.Minden tigris négy lábal születik, s eggyel növeli a populáció számát. Ha ez nemtörténik meg, akkor a bengáliak közé sorolódik. Az alfaj a tigris életciklusa alatt nemváltozhat, lekérdezésére egy metódus áll rendelkezésre. A Tigris osztálynak meg kellvalósítani az Emlos-ben absztraktként definiált megy() metódust.
Példa 3.19 Tigris.javapubl i c cl ass Ti gr i s ext ends Eml os{
publ i c st at i c f i nal i nt BENGALI = 1;publ i c st at i c f i nal i nt KARDFOGU = 2;pr i vat e f i nal i nt al f aj ;publ i c Ti gr i s( i nt al f aj ) {
Syst em. out . pr i nt l n( „Megszul et et t egy t i gr i s”) ;popul aci o++; l abakSzama = 4;
thi s. al f aj = al f aj ;}publ i c Ti gr i s( ) {
t hi s( BENGALI ) ;}publ i c i nt get Al f aj ( ) {
ret urn al f aj ;}publ i c voi d megy( ) {
Syst em. out . pr i nt l n( „A t i gr i s megy”) ;}
}
Az Ember osztály szintén az Emlos-ok közé tartozik, akinek nevét születésekormeg kell adni. Ez a név a késő bbiekben megváltoztatható. Az Ember-nek (ahhoz,hogy példányosítható legyen) szintén meg kell valósítania a megy() metódust.
Példa 3.20 Ember.javapubl i c cl ass Ember ext ends Eml os{
pr i vat e St r i ng nev;publ i c Ember ( St r i ng nev){
Syst em. out . pr i nt l n( „Megszul et et t ” + nev) ;popul aci o++;t hi s. nev = nev;l abakSzama = 2;
}publ i c St r i ng get Nev( ) {
r et ur n nev;}publ i c voi d set Nev( St r i ng uj Nev){
nev = uj Nev;}publ i c voi d megy( ) {
Syst em. out . pr i nt l n( nev + „ f el kel es j ar ”) ;}
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 31/80
Utoljára maradt Superman, aki több OO különlegességgel is szolgál. Először isOO szempontból Superman nem lehet más osztályok őse, nem lehetnekleszármazottai. Ezt a final kulcsszó alkalmazásával érhetjük el. Másodszor, nem aMadar objektumból származik, mégis tud repülni. Ennek semmi akadálya, hamegvalósítja a Repulo interfészt. A harmadik lényeges tulajdonsága pedig, hogyegyedi (singleton), tehát a konstruktora csak egyszer hívható meg. Ennek
biztosítására egy tervezési mintát alkalmazhatunk. A lényeg az, hogy egyközvetlenül nem elérhet osztály szintű adattag tárolja az objektumot, s egy osztályszintű metódus segítségével kérhetjük őt el. Ez a metódus megvizsgálja, hogylétrejött-e már az objektum (ha nem, akkor létrehozza), majd visszaadja azt. Ehhez aművelethez a konstruktort is el kell rejtenünk, hogy más osztály ne férjen hozzá, netudja példányosítani osztályunkat.
Példa 3.21 Superman.javapubl i c f i nal cl ass Superman ext ends Eml os
i mpl ement s Repul o{pr i vat e stat i c Super man s;pr i vat e Superman( ) {
Syst em. out . pr i nt l n( „Super man megszül et et t ”) ;popul aci o++;l abakSzama = 2;
}publ i c st at i c Superman getSuperman( ) {
i f ( s == nul l ) s = new Superman( ) ;r et ur n s;
}
publ i c voi d set LabakSzama( i nt uj Labszam) {Syst em. out . pr i nt l n( „Super man l ábai sér t het et l enek”) ;}publ i c voi d gol yot Megal l i t ( ) {
Syst em. out . pr i nt l n( „Super man megal l i t egy gol yot ”) ;}publ i c voi d megy( ) {
Syst em. out . pr i nt l n( „Super man set al , de ha si et nikel l , repul ni i s t ud”) ;
}publ i c voi d r epul ( ) {
Syst em. out . pr i nt l n( „Super man r epul ”) ;}}
Minden kivételes képessége ellenére Superman sincs felmentve az absztraktmetódusok, illetve az implementálni kívánt interfészek metódusainak megvalósításaalól. Ezért meg kell adnunk a megy(), illetve a repul() metódus implementációját.
A Superman osztály deklarációjában felülírtuk a setLabakSzama() metódust is,hiszen Superman sosem veszti el lábait. Ezt nem gátolja meg semmi, hiszen az adottmetódus nem lett final kulcsszóval ellátva, így tetszés szerint megváltoztatható az
üzenetre adott válasz.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 32/80
4. „Rendteremtés”
Eddigi munkáink során minden osztálydefinícónknak külön file-t nyitottunk, sugyanabba a könyvtár mentettük azokat. A kód sem tartalmazott semmilyenmagyarázatot a választott megoldás indoklására. Az eddigi programjaink során ezek
a tények nem is okoztak problémát, hiszen kevés és egyszer ű forrásaink átlátásáhoznem kellett nagy meger őltetés. Ha azonban egy nagyobb feladat megoldásáhozválasztjuk a Java technológiát, szükség lehet a forrásaink öndokumentálására,melyeket újraolvasva vissza tudunk emlékezni arra, hogy mit és miért tettünk.Emellett a forrásokfile-ok könnyebb áttekintésére szükségünk lehet azok egymástólvaló jobb elszeparálására, az összetartozó részek összefogására. Err ől, ezekmegvalósításának módjairól fog szólni ez a fejezet.
4.1. Csomagok
A komolyabb Java programok nem két-három osztályból, hanem több százból,nem ritkán több ezerből állnak. Ha ezeket az osztálydefiniciókat egy könyvtárbantárolnánk, akkor nehéz lenne megtalálni az éppen módosítani, vagy csak felhasználnikívánt forrást. Az egyik megoldásunk az lehetne, hogy könyvtárszerkezetekbeszétszórjuk a file-okat, de ekkor a <CLASSPATH> környezeti változónknak kellenetúl sok értéket beállítani. Ezt a problémát felismerve vezették be a Java-ban acsomag fogalmát. A csomag a logikailag összefüggő osztálydefiníciók gyű jteménye.A csomagot névvel kell ellátnunk, s belőlük hierarchikus szerkezetet építhetünk fel.Ez a szerkezet egyben megfelel egy könyvtárstruktúrának is, viszont ennek aszerkezetnek csak a gyökerét kell megadni a fentebb említett környezeti változóba.
Egy osztályt a package kulcsszó használatával rendelhetjük hozzá egycsomaghoz. (Példa 4.1) A kulcsszót a csomag nevével a definíció legelején lehetmegadni. Miután hozzárendeltük a csomaghoz az osztályt, a lefordított class file-unkat a csomaghierarchiának megfelelő könyvtárstruktúrába kell másolni. Ha nemadunk meg csomagdeklarációt, akkor a létrehozott osztály egy úgynevezett névtelencsomagba kerül. (Ezt használtuk ki eddig)
Egy más csomagban elhelyezett osztály használatának több módja lehet. Azegyik, hogy a használatkor csomagnévvel minősítjük az osztályt (allat.Allat, vagyallat.emlos.Superman), vagy a forrásfile legelején az import kulcsszó használatávalmegadjuk, hogy melyik osztályt melyik csomagban találhatja meg a fordító és afuttató környezet. (Példa 4.3) A * karakter használható egy teljes csomag
beimportálására (elérhetővé tételére). (Példa 4.2) A Java egyedüliként a java.langcsomag importálását nem teszi kötelezővé (természetesen a saját csomag mellett). Ezminden Java program számára import utasítás nélkül is elérhető, s a nyelv alapvető osztályait tartalmazza (String, System, stb.). Importáláskor figyelni kell arra, hogy aművelet nem rekurzívan történik, tehát egy teljes csomag beimportálásakor nemlesznek elérhetőek az alcsomagok osztályainak definíciói. A másik fontos szabály
pedig, hogy egy utasításban csak egy osztály (esetleg a *-gal egy teljes csomag)importálható. Ha nekünk több csomagra, vagy osztályra van szükségünk, akkorazokat külön sorban kell megadni.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 33/80
Ezek után a 3.6 fejezet egy lehetséges csomagstruktúrája:
o allat Allat.class Repulo.class
o madar Fecske.class Strucc.class
o emlos Tigris.class Ember.class Superman.class
Példa 4.1 Csomagdefiníció az Allat.java file-banpackage al l at ;
publ i c abst r act cl ass Al l at {. . .
}
Példa 4.2 Alcsomag használata és teljes csomag importálása a Madar.java-banpackage al l at . madar ;
i mpor t al l at . *; / / A Repul o és az Al l at oszt ál y mi at t
publ i c abst r act cl ass Madar ext ends Al l at i mpl ement s Repul o{. . .
}
Példa 4.3 Egy adott osztály importálása más csomagbólpackage al l at . eml os;
i mpor t al l at . Repul o; / / Csak ez az oszt ál y kel l
publ i c f i nal cl ass Superman ext ends Eml osi mpl ement s Repul o{
. . .}
Emellett a teljes struktúrát betömöríthetjük egy jar (Java Archive) kiterjesztésű file-ba, amelyet a <CLASSPATH>-ban megadva szintén elérhetővé válnak azosztályaink. A jar file másik előnye a kényelem, hiszen nem teljes könyvtárstrukúrátkell a megrendelő felé továbbítani, csak egy file-t. A jar egy zip tömörítési eljárássalkészült archívum, amely az Manifest.mf file-lal van kiegészítve. Ez a file tartalmazzaaz archívum fontosabb adatait (verzió, felhasznált külső csomagok), köztük egy
bejegyzést a futtatható osztályra. Ezt felhasználva az elterjedtebb operációsrendszerek képesek futtatni egy jar-t, nem kell hozzá parancsfile-t sem mellékelni.Egy archívum a jar parancssori programmal készíthető, melynek paraméterezésér ől
paraméter nélküli futtatás útján kaphatunk információt.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 34/80
4.2. Megjegyzések, dokumentáció-készítés
Az első, s talán legfontosabb, hogy mindig dokumentáljuk forrásainkat, ezzelelősegítve, hogy akár hónapokkal késő bb elővéve a programot, könnyen izolálnitudjuk azokat a helyeket, amelyek az újabban felmerülő igények miatt módosításra
szorulhatnak. A másik előnye a megjegyzések használatának, hogy az osztályainkatfelhasználó szoftverfejlesztők könnyebben átláthassák, hogy miért készült az adottosztály, milyen szolgáltatásai vannak, s melyiket mire lehet használni.
A Java nyelv három különböző megjegyzés-jelölést támogat. Az első a / / ,amellyel sor végéig tartó dokumentációs szöveget illeszthetünk a kódba. Az ígymegadott szöveget a fordító nem próbálja meg értelmezni, ezért alkalmas rövidebbmegjegyzések, emlékeztetők kódba illesztésére. Ha egy sor nem elég, akkorhasználhatjuk a többsoros megjegyzés lehetőségét. (/* és */) Ez esetben a nyitó észáró jelek között lévő szöveg kerül ki a fordítás hatóköre alól.
A harmadik az úgynevezett dokumentációs megjegyzés (/** és */), amelyetazért hoztak létre, hogy a forrást és a róla készülő dokumentációt ne kelljen a
programozónak szétválasztani. Így a program módosításakor látszik, hogy adokumentációt hol kell átírni. A dokumentációs megjegyzéssel ellátott forrást egyspeciális programnak ( javadoc) átadva az alkalmazás html formátumú leírást generála dokumentációs megjegyzésben megadott adatok figyelembe vételével. A javadocáltal támogatott kulcsszavak: (Példa 4.4)Az osztályra vonatkozó információk:
@author <A kód készítő je>
@version <A kód verziószáma> @see <Kapcsolódó osztály> @since <JDK verziószáma>
Metódusokra vonatkozó információk előtt: @param <Paraméter neve> <Paraméter leírás> @return <Visszatérési érték értelmezése> @see <Hivatkozás más osztályra, vagy egy másik metódusra> @exception <Exception típusa> <A kivétel keletkezésének okai> @link <Hivatkozás más metódusra>
Példa 4.4 Az Ember osztály dokumentációs megjegyzésekkelpackage al l at . eml os;/ * ** Egy Ember obj ekt umot r epr ezent ál ó oszt ál y** @aut hor Deák Lász l ó* @ver si on 1. 0 2002/ 11/ 28* @see al l at . eml os. Eml os, al l at . Al l at*/
publ i c cl ass Ember ext ends Eml os{/*** Az ember nevét t ar t al mazó adat t ag*/
pr i vat e St r i ng nev;
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 35/80
/ * ** Konst r uktor , amel y t udat j a a f el használ óval , hogy* l ét r ej öt t egy új obj ekt um, val ami nt beál l í t j a az* al apér t el mezet t ér t ékeket*
* @param nev A l ét r ehozandó Ember neve*/publ i c Ember ( St r i ng nev){
Syst em. out . pr i nt l n( „Megszul et et t ” + nev) ;popul aci o++;t hi s. nev = nev; l abakSzama = 2;
}/ *** Az obj ektum nevét adj a vi ssza** @r etur n Az Ember t í pusú obj ekt um neve
*/publ i c St r i ng get Nev( ) {r et ur n nev;
}/ *** Az obj ekt um nevét megvál t ozt atni képes metódus** @par am nev A Ember obj ekt um új neve*/
publ i c voi d set Nev( St r i ng uj Nev){nev = uj Nev;
}/ *** A hel yvál t ozt atáshoz szükséges metódus** @see Eml os#hel yet Val t ozt at ( )*/
publ i c voi d megy( ) {Syst em. out . pr i nt l n( nev + „ f el kel es j ar ”) ;
}}
A Java fejlesztő
i készletéhez (JDK) jár egy tömörített file, src.jar
19
néven. Ezcsak azokon a gépeken található meg, ahol a Java telepítésekor kérték a forrásoktelepítését is. Ebben a file-ban található a környezetbe integrált osztályok forrása,ellátva rengeteg dokumentációs megjegyzéssel. A dokumentációs megjegyzésekbőllétrehozott html oldalak elérhetőek a http://java.sun.com/docs/1.4/api/index.htmlcímen, illetve letölthetőek az Sun Java-s oldalairól20. Ezeket a file-okat ésweboldalakat tanulmányozva mindenki kellő információt szerezhet a dokumentációsmegjegyzések kulcsszavairól, valamint egy jól felépített csomagstruktúra, illetvedokumentáció készítésér ől.
19 Kitömöríthető a már megismert jar programmal, de egy átlagos zip tömörítő-programmal is20 Természetesen a javadoc programot használva mi is elkészíthetjük a forrásokból a dokumentációt
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 36/80
5. Alapvető osztályok
A Java alaposztályai között található néhány, amely szinte kivétel nélkülminden Java technológián alapuló programban szerepel. Ide tartozik a tömbökkezelését megvalósító osztály (a Java-ban a tömb is egy osztály), a System, vagy az
eddig is sok helyen alkalmazott String. Ezek két alapvető csomagban kaptak helyet.Az egyik a java.lang csomag, a másik pedig a java.util csomag. Ezekr ől szól ez afejezet.
5.1. Tömbök kezelése21
Mint már a fejezet bevezető jéből kiderülhetett, a Java-ban a tömböketobjektumok reprezentálják (például tudják saját méretüket), azonban ezeknek azobjektumoknak a kezelése eltérhet a többi osztály kezelésétől.
Ha egy tömböt akarunk létrehozni, akkor a típus megadásakor a tömböt alkotóelemek típusát kell megadnunk, illetve a tömbképző operátorral ( [] ) jelölnünk, hogyez esetben nem egy egyszer ű objektumról (vagy egyszer ű típusról) van szó, hanemaz adott típusnak megfelelő objektumokat (vagy értékeket) tartalmazó tömbr ől(Példa 5.1). A példányosítás a többi osztálynak megfelelően a new operátorraltörténik, de itt sem konstruktort kell megadnunk, hanem az elemek típusát, valaminta tömbben tárolható értékek számát. Emellett egy tömb inicializálható elemeinekfelsorolásával is. A felhasznált tömbök mérete futás alatt nem változtatható (statikusméret), így felhasználás előtt (mielőtt hivatkoznánk valamelyik elemére) mindiginicializálni kell.
A tömb elemeit a többi nyelvhez hasonlóan annak indexével érhetjük el. Azindexelés 0-val kezdődik, s a méretnél eggyel kisebb értékig terjed. A tömb méreteaz objektum length adattagján keresztül érhető el (Példa 5.1)
Példa 5.1 Tömb használatapubl i c cl ass Fonok extends Al kal mazot t {
pr i vat e st at i c f i nal i nt MAX_BEOSZTOTTAK = 24;pr i vat e i nt al kal mazot t I ndex;pr i vat e Al kal mazot t [ ] beoszt ot t ak;. . .
Fonok( St r i ng nev, i nt f i zet es, i nt nyel vek) {super ( nev, f i zet es) ;nyel vekSzama = nyel vek;beoszt ot t ak = new Al kal mazot t [ MAX_BEOSZTOTTAK] ;
}publ i c voi d addBeoszt ot t ( Al kal mazot t beoszt ot t ) {
i f ( beoszt ot t I ndex < beoszt ot t ak. l engt h)beoszt ot t ak[ beoszt ot t I ndex++] = beoszt ot t ;
}. . .
}
21 A sokat használt main metódus args argumentuma is egy tömb (String-ekből áll), s ezen keresztül adódnak át a program paraméterei
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 37/80
5.2. A java.lang csomag
A java.lang csomag a nyelv alaposzályainak készlete, amelynek szükségességétaz is jelzi, hogy a Java egyetlen olyan csomagja, amelyet nem kell importálnunk ahasználathoz. Ebben a fejezetben csak ízelítőt adunk a csomag osztályainak
szolgáltatásairól. Aki ennél többre vágyik, az tanulmányozza a 4.2 fejezet végén máremlített API dokumentációt.
Talán a legfontosabb csomag legfontosabb osztálya a java.lang.Object osztály.Mint már említettük, minden Java-ban íródott osztály (közvetlenül, vagy közvetve)ennek az osztálynak a leszármazottja.
Legfontosabb metódusai:o public String toString() - Az osztály String-reprezentációját adja visszao public boolean equals(Object) - Eldönti, hogy a paraméterben megadott
objektum megegyezik-e az aktuális objektummal
o public void finalize() - Destruktor jellegű metódus, de lefutásának pontosideje nem meghatározhatóo public final Class getClass() - Az objektum osztályát adja vissza
A csomag tartalmaz minden primitív típushoz egy úgynevezett csomagolóosztályt, amely konstruktorának átadva egy primitív típusú értéket, egy objektumotkapunk, amit már használhatunk mindenütt, ahol erre szükség van (példáulobjektumok tárolását lehetővé tevő veremben, vagy listában) A primitív típusokhoztartozó csomagoló osztályok neveit a Táblázat 5 tartalmazza. Minden csomagolóosztályhoz tartozik konstans a maximális, illetve a minimális felvehető értéktárolására (csomagoló.MAX_ VALUE, csomagoló.MIN_VALUE) A nem egész
típusok csomagoló osztályainak van konstansa a pozitív végtelen, a negatív végtelen,illetve a nem szám értékek jelzésére (pl.: Double.Nan, Float.POSITIVE_INFINITY,Float.NEGATIVE_INFINITY)
Primitív típus Csomagoló osztályByte ByteShort ShortInt IntegerLong LongFloat Float
Double DoubleChar CharacterBoolean BooleanVoid Void
Táblázat 5
Ebben a csomagban található a String osztály is, amelyr ől már nagyon sok szóesett az eddigiekben. Optimalizálási és hibakeresési megfontolásokból azonban megkell említeni még pár dolgot. A String hossza kötött, az futás közben nemváltoztatható. (Ennek oka, hogy a háttérben egy char[] tárolja az adatokat), ezért két
String + jellel való összekapcsolásakor (konkatenáció) mindig egy újabb objektumkeletkezik, még több memóriát foglalva. Ennek feloldására a StringBuffer (lásd
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 38/80
lentebb) osztály használható. A másik lényeges dolog, hogy a String típusú objektumegy objektum, így ha az == jellel hasonlítunk össze két Stringet, az hamis értéket fogvisszaadni, függetlenül az objektumok tartalmától. (Referencia szerintiösszehasonlítás történik) Ennek feloldására a String osztály equals(Object), illetveequalsIgnoreCase(Object) metódusa használható.
A StringBuffer (jó közelítéssel) a String osztály dinamikus méretű megfelelő je.Konkatenáció az append() metódusaival érhető el, amely a polimorfizmusnakköszönhetően bármely primitív vagy összetett típust képes a buffer eddigitartalmához f űzni. Van lehetőség a beszúrásra (az insert(...) metódus különböző
paraméterezettségű formái), a tárolt karakterek megfordítására (reverse()), s egyébszolgáltatások kihasználására. A StringBuffer toString() metódusával az objektumotújra String-é alakíthatjuk.
A Class osztály egy objektum-felderítést segítő lehetőség. Használatával
eldönthető, hogy egy adott objektum osztálya milyen konstruktorokkal(getConstructors()), metódusokkal (getMethods()) és adattagokkal (getFields())rendelkezik, illetve további metódusok használhatóak a többi jellemző megállapítására. Emellett a Class osztály rendelkezik egy statikus metódussal,amellyel egy osztály nevét felhasználva a new operátor nélkül hozhatunk létre egyobjektumot (forName(String))
A Math osztály a matematikai problémák kezelésében lehet nagy segítségünkre.Minden metódusa osztály szintű, így nincs szükség a példányosításra.
Konstansok:o PI , E (a természetes logaritmus alapszáma)
Fő bb metódusok:o min(szám típus, szám típus) - két szám közül a kisebb kiválasztásárao max(szám típus, szám típus) - két szám közül a nagyobb kiválasztásárao abs(szám típus) - abszolút érték meghatározásao trigonometrikus függvények számítását lehetővé tevő metódusoko kerekítések, hatványozások
A System osztály segítségével kapcsolatot teremthetünk a futtató környezettel.Eddigi programjainkban használtuk már az out adattagját, amely az alapértelmezett
kimenetet jelenti (ez általában a képernyő), de létezik egy adattag az alapértelmezett bemenetre (System.in), illetve az alapértelmezett hiba-kimenetre (System.err). A
System osztály (több más mellett) használható még a program befejezésénekkikényszerítésére (System.exit(int)), ahol megadható egy terminálási érték, valaminta szemétgyű jtés „kézi” indítására (System.gc()). Ez az osztály biztosít számunkra,illetve a többi osztály számára lehetőséget a rendszerváltozók értékeineklekérdezésére (getProperties(), getProperty(String)), illetve egy rendszerváltozó
beállítására (setProperty(String, String)) A Java által támogatott fontosabbrendszerváltozókat a Táblázat 6 tartalmazza. Hasznos tulajdonság lehet még azaktuális idő lekérdezése (currentTimeMillis()), amely az 1970. január 1-je óta eltelt
időt adja vissza ezredmásodpercben (lásd még a java.util.Date osztályt - Példa 5.4)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 39/80
A Thread osztályról, valamint a Runnable interfészr ől részletesebben is szó lesza 8-as fejezetben, így azok tárgyalását most mellőzzük.
S végül a Comparable interfész, amelyet szintén a java.lang csomag tartalmaz.Ez az interfész egy metódust határoz meg az őt implementáló osztály számára.
o public int compareTo(Object o)A metódus feladata, hogy egy egész értékkel jelezze, hogy az aktuális objektum
nagyobb (pozitív), kisebb (negatív), esetleg egyenlő (nulla) a paraméterként kapottobjektummal (Példa 5.2) Ezt az interfészt használják fel (többek között) a következő alfejezetben ismertetett osztályok objektumok rendezéséhez.
Rendszerváltozó Az érték leírása j ava. ver si on JRE verziója j ava. vendor JRE szállítója
j ava. vendor . ur l JRE szállítójának URL címe j ava. home Java könyvtára j ava. vm. speci f i cat i on. ver si on JVM specifikációjának verziója j ava. vm. speci f i cat i on. vendor JVM specifikációjának szállítója j ava. vm. speci f i cat i on. name JVM specifikációjának neve j ava. vm. ver si on JVM verziója j ava. vm. vendor JVM szállítója j ava. vm. name JVM neve j ava. speci f i cat i on. ver si on JRE specifikációjának verziója
j ava. speci f i cat i on. vendor JRE specifikációjának szállítója j ava. speci f i cat i on. name JRE specifikációjának neve j ava. cl ass . ver si on Java osztályformátumának
verziószáma j ava. cl ass . pat h Java classpath j ava. ext . di r s os. name Operációs rendszer neveos. ar ch Operációs rendszer architektúrájaos. ver si on Operációs rendszer verziójaf i l e. separ at or File-ok elválasztó jele (Unix:/
Win:\)pat h. separ at or Útvonalak elválasztójele(Unix(:)
Win(;))l i ne. separ at or Sortörés karaktere(\n)user . name Felhasználó neveuser . home Felhasználó könyvtárauser . di r Aktuális könyvtár (Windows alatt
nincs)
Táblázat 6
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 40/80
Példa 5.2 A Comparable interfész használatapubl i c cl ass Al kal mazot t i mpl ement s Ki r ughato, Compar abl e{
. . .publ i c i nt compat eTo( Obj ect o) {
r et ur n f i zet es - ( ( Al kal mazot t ) o) . get Fi zet es() ;
}}
5.3. A java.util csomag
A java.util olyan osztályokat tartalmaz, amelyek nélkülönözhetetlenek egy jólfelépített alkalmazás számára. Itt találjuk meg a listák, dinamikus tömbök, szótárakosztályát (Collections Framework 22), a nemzetköziesítést segítő osztályt, a dátum ésidő kezeléséhez szükséges segédosztályokat, s olyan fontos osztályokat, mint avéletlenszám-generátor, vagy a String felbontására alkalmas StringTokenizer.
Ezek részletes bemutatása a terjedelemi korlátok miatt elmarad, viszontszeretnék kiemelni néhányat közülük. Ilyen a Collection interfész, amely aCollections Framework alapinterfésze. Ebben vannak felsorolva azok a metódusok,amelyet minden gyű jteménynek implementálnia kell. A részleteket lásd az APIdokumentációban.
A Collections osztály a Collection interfészt implementáló objektumok számáranyújt hasznos szolgáltatásokat. Ide tartozik (többek között) a maximum és minimumérték meghatározása, illetve a rendezés is (Példa 5.3), amelyeknél a Comparableinterfészt használja ki alapértelmezés szerint, de saját Comparator objektumot is
megadhatunk.
Nagyon fontos még a Vector osztály, amely a Java közösség dinamikus tömbje.(Példa 5.3) Általánosságának köszönhetően bármilyen objektum belepakolható, ígyalkalmas akár hibrid tömbök létrehozására is.
Legfontosabb metódusai:o public void addElement(Object) - új elem hozzáf űzéseo public boolean removeElement(Object) - egy elem törléseo insertElementAt(Object, int) - irányított beszúrásao public int size() - méretmeghatározás
o public Enumeration elements() - az elemek egy Enumeration-jét (lásdlentebb) adja vissza
A Enumeration interfész egy felsorolás típus, amellyel az elemeket járhatjukvégig, mindig csak az aktuális elemhez hozzáférve, s a következőt elérve (láncoltlista - Példa 5.3)
Metódusai:o public boolean hasMoreElements() - meghatározza, hogy van-e még
feldolgozásra váró elem a listábano public Object nextElement() - a lista következő elemét adja meg
22 Gyű jtemény Keretrendszer
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 41/80
A gyű jtemény keretrendszer legfontosabb osztályai közé tartozik a Hashtable,amely az adatok kulccsal ellátott listája (szótár) Tehát nem értékeket, hanemértékpárokat tartalmaz, amelyek közül az egyik a teljes listára nézve egyedi. Ennek atulajdonságának köszönhetően egy hatékonyabb keresést tud megvalósítani.
A csomag fontos része még a Date osztály, amely dátumok tárolására alkalmas.A dátumot mindig egy egész érték jelzi, amely megegyezik az 1970. január 1 ótaeltelt ezredmásodpercek számával. Alkalmas azonban formázott megjelenítésre is,amely az alkalmazás felületén megjelenítendő dátumok olvashatóságán sokat segít.(Példa 5.4)
A StringTokenizer String típusú objektumok részsztingekre való bontásábansegít. Konstruktorában meg lehet adni, hogy mi vagy mik alkotják az elválasztókaraktereket. Ezután a hasMoreTokens(), illetve a nextToken() metódusokhasználatával részleteiben férhetünk hozzá a String-hez. A countTokens() metódus
használatával megtudhatjuk, hogy mennyi feldolgozandó részlet van még hátra.
Példa 5.3 Objektumok rendezései mport j ava. ut i l . * ;
publ i c cl ass Al kal mazot t Rendezo{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
Vect or l i st a = new Vect or ( ) ;l i st a. addEl ement ( new Al kal mazot t ( „Andr ás”, 75000) ) ;l i st a. addEl ement ( new Al kal mazot t ( „Géza”, 85000) ) ;l i st a. addEl ement ( new Al kal mazot t ( „I st ván”, 50000) ) ;l i st a. addEl ement ( new Fonok( „Bél a”, 175000) ) ;l i st a. addEl ement ( new Al kal mazot t ( „Már t on”, 67000) ) ;/ / A Vect or r endezése a f i zet és al apj ánCol l ect i ons. sor t ( l i st a) ;Enumer at i on e = l i st a. el ement s( ) ;whi l e( e. hasMor eEl ement s( ) )/ / A beszédesebb ki í r ás ér dekében f el ül kel l í r ni az/ / Al kal mazot t oszt ál y t oSt r i ng( ) met ódusát
Syst em. out . pr i nt l n( e. next el ement ( ) ) ;}
}
Példa 5.4 Az aktuális dátum kiírása a képernyő rei mpor t j ava. ut i l . Dat e;
publ i c cl ass Akt ual Datum{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
Dat e d = new Dat e( Syst em. cur r ent Ti meMi l l i s( ) ) ;/ / vagy Dat e d = new Dat e( ) ;Syst em. out . pr i nt l n( d) ;
}
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 42/80
6. Kivételkezelés
Egy jól megírt program működése során is léphetnek fel hibák, ami abbóladódik, hogy a programozó a fejlesztés alatt költséghatékony módon nem készülhetfel minden eshetőségre, hiszen ha minden egyes kódsorban a lehetségesen
felmerülhető hibákat ki kellene szűrni, akkor az idő nagy részét az ehhez szükségesvezérlési szerkezetek megírása vinné el.
A másik jelentős probléma, hogy a OOP szellemiségének megfelelően a programjainkat komponensekből, előre megírt szoftverelemekből építjük fel, ezértegy szoftverkomponens írásakor még nem tisztázott, hogy mit kell kezdeni azesetlegesen fellépő hibákkal. Azt csak a komponens használója (egy magasabbabsztrakciós szinten) tudja meghatározni, ezért megfelelő módon el kell választani ahiba keletkezésének helyét, illetve a hibakezelő kódrészletet. Például egy adottadatbázissal kapcsolatot teremtő komponens nem tudhatja, hogy mi történjen, ha a
kapcsolat felépítése nem sikerült. Írjon ki egy informatív üzenetet (milyen nyelven?),vagy esetleg próbáljon meg kapcsolatba lépni egy másik adattárolóval (melyikkel?)Ezekre a kérdésekre a kapcsolatot biztosító osztály készítő je nem tudja, és nem istudhatja a választ. Nem az ő feladata eldönteni, hogy ilyen esetekben mi történjen.
Ezt régebben úgy kezelték, hogy a meghívott metódus, függvény, vagy eljárás ahibának megfelelő hibakóddal tért vissza, vagy ahol ez nem volt lehetséges, logikaiváltozókat állított be. Így azonban egy újabb kellemetlenségbe ütközünk. Afüggvényhívás több hibát is generálhat, így a hívó félnek minden lehetségesvisszatérési értéket meg kell vizsgálnia, ráadásul minden egyes híváskor. Ez egy
nagyobb rendszerben olvashatatlanná, átláthatatlanná teszi a kódot, ezért (illetve azidőhiány miatt) a programozók többsége nem foglalkozott a visszatérési értékkel,figyelmen kívül hagyta azt. Ez a megközelítés pedig nagyobb rendszerek eseténhozzájárult a programok megbízhatóságának romlásához.
A gondok megoldására a 60-as években kifejlesztették a kivételkezeléselméletét, amely azonban csak az OO rendszerek elterjedésével teljesedhetett ki.Ennek a megoldásnak a Java-s megvalósításáról szól ez a fejezet.
6.1. A Java kivételkezelése
A Java kivételkezelésének célja a futási idő ben keletkezett hibák kiszűrése,valamint megfelelő kezelése. Az ilyen jellegű hibákat ezen a platformon Exception-nek (kivételnek) nevezik. A felmerülő hibák sokféleségének kezelését a Java az OOPlehetőségeinek kihasználásával éri el. A nyelvi elemek szintjén nincs különbség akivételek között, azok közös osztályból származnak (illetve közös interfésztimplementálnak), így kezelésük egységesíthető.
A kivételkezelés talán legegyszer ű bb példája az osztás. A programok többségeáltalában sok ilyen műveletet tartalmaz, s a műveletek elvégzése után az eredménytfelhasználja a késő bbiekben. Ezzel nem is lenne gond mindaddig, amíg az osztótmegfelelően kontrolálni tudjuk. A probléma akkor következik be, ha az osztó egyváltozó, vagy adattag, amely viszont már felveheti a 0 értéket. Az egyik lehetséges
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 43/80
megoldás, hogy minden osztás előtt ellenőrizzük az osztó értékét, s csak akkormegyünk tovább, ha az nem nulla. Ez több osztás esetén komplikált művelet, hiszenmindig el kell végeznünk az ellenőrzést. Ekkor lép előtérbe a kivételkezelés. Akoncepciónak köszönhetően a „gyanús”, kivételes programállapotot eredményezhető sorokat összefogva, s hozzá egy úgynevezett kivételkezelőt megadva a probléma egylépésben megoldható. Ekkor az adott blokkban fellépő kivételeket egységesen, egyhelyen kezelhetjük, jól elválasztva egymástól a program logikáját megvalósító részt,illetve a hibák lekezeléséért felelős kódrészt.
Ennek megvalósítására a try blokk használható. A try blokkutasításokat zárközre, amelyeket a futás alatt végig felügyelete alatt tart. Egy ilyen blokkhozmegadható tetszőleges számú (de legalább egy) catch ág, amelyek az esetlegesenfellépő hibák kezelését biztosítják. Ha valahol kivétel lép fel (váltódik ki), akkor avirtuális gép megpróbál olyan catch ágat találni, amely képes annak kezelésére. Egycatch ág akkor képes egy hiba kezelésére, ha paramétere megegyező típusú akiváltott kivétellel, vagy annak őse. A catch ág egy szigorúan egyparaméteresmetódusként fogható fel, amely paraméterként megkapja a fellépő kivételt, amelyetazután tetszőlegesen felhasználhat a hibakezelés során. (Természetesen a kivételobjektumot nem kötelező felhasználni, hiszen néha a típusa elég ahhoz, hogy a
programot a kivételes állapotból értelmes mederbe tereljük) A try-catch blokkszintaktikája: (Példa 6.1)try{
/ / Gyanús ut así t ások}cat ch( Tí pus1 azonosí t ó1) {
/ / Hi bakezel ő kódsor
}cat ch( Tí pus2 azonosí t ó2) {. . .}cat ch( Tí pusn azonosí t ón) {
/ / Hi bakezel ő kódsor}
Vannak olyan kivételek, amelyek bizonyos események hatására automatikusankiváltódnak. Ilyen például a nullával való osztás, vagy az indexhatár-túllépés, svannak olyanok, amelyek kiváltásáról a programozónak kell gondoskodnia. Az első kategóriába tartozó kivételek kezelése nem kötelező, hiszen ez nagymértékbennövelné a kódok méretét, s a program komplexitását. Egy kivételt a throw utasítással
válthatunk ki, oly módon, hogy a kulcsszó után szóközzel elválasztva megadunk egykivételobjektumot.(Példa 6.1) A programozó által kiváltott kivételek lekezelésekötelező, hiszen csak így garantálható a biztonságosan futó program.
Természetesen a kivételeket nem tudjuk mindig az őt kiváltó helyen kezelni. Haegy metódus végrehajtásakor abban kivétel keletkezhet, s mi ezt nem akarjuk, vagynem tudjuk helyben (az adott metóduson belül) lekezelni, akkor tovább kelldelegálnunk egy magasabb szintre (az adott metódust hívó metódus felé), mindaddig,amíg el nem érjük azt a szintet (metódust), amely már elegendő információvalrendelkezik a megfelelő intézkedések elvégzéséhez. Ezt a throws kulcsszóval
tehetjük meg, amelyet a metódus fejlécében kell megadni, utána felsorolva azelőfordulható, de általunk kezelni nem kívánt kivételek típusait. (Példa 6.4)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 44/80
6.2. „ Beépített” kivételek
Mint már említésre került, léteznek olyan kivételek, amelyek bizonyosesemények hatására automatikusan kiváltódnak. Ezekr ől, illetve ezek kezelésér ől adízelítőt a Példa 6.1. A program paraméterétől függően megpróbál végrehajtani egy
olyan utasítást, amely kivételt vált ki. Megfigyelhető továbbá „a programozó általkiváltott kivétel” lehetősége, valamint a kivételek kezelése is.
Példa 6.1 Beépített kivételekpubl i c cl ass Except i ons{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {try{
i f ( ar gs[0] . equal s("nul l a") ) {i nt i =0;i / = i ;
} el se i f ( ar gs[ 0] . equal s( "t omb") ) {
St r i ng el em = ar gs[ - 1] ;} el se i f ( ar gs[ 0] . equal s( "szam") ) {
Doubl e. par seDoubl e( ar gs[ 0] ) ;} el se i f ( ar gs[ 0] . equal s( "except i on") ) {
t hr ow new Except i on( ) ;} el se i f ( ar gs[ 0] . equal s( "i smer et l en") ) {
t hr ow new Except i on( "Ki vál t ot t ki vét el ") ;} el se {
Syst em. out . pr i nt l n ( "Ni ncs ki vét el ") ;}
}cat ch(Ar r ayI ndexOut Of BoundsExcept i on ai oobe){
Syst em. out . pr i nt l n( ai oobe) ;}cat ch( Ar i t hmet i cExcept i on ae) {
Syst em. out . pr i nt l n( ae. get Message( ) ) ;}cat ch( NumberFormat Except i on nf e) {
System. out . pr i nt l n( nf e. t oSt r i ng( ) ) ;}cat ch( Except i on e) {
e. pr i nt St ackTr ace( ) ;}f i nal l y{
Syst em. out . pr i nt l n( "Ez mi ndi g l ef ut ") ;}
}
}
Ha fordítás után a programot a j ava Except i ons nul l a paranccsalfuttatjuk, akkor a try blokkon belüli if utasításokban megadott feltételek közül azelső ad vissza igaz értéket, így az ott megadott kó fog érvényesülni. Ekkor a programmegpróbál nullával osztani, amelynek hatására egy ArithmeticException váltódik ki.A program futása megszakad, s a vezérlés átkerül a megfelelő kivételkezelő blokkra.Ez a blokk a kivétel objektum üzenetét írja a képernyőre. Ha argumentumként atomb karaktersort adjuk meg, akkor a második if feltétele válik igazzá, s egy Stringtípusú változóba próbálja elraktározni az args tömb -1-edik elemét. Ez egy
indexhatártúllépés (ArrayIndexOutOfBoundsException), amelyet úgy kezelünk le,hogy képernyőre írjuk a kivételobjektumot (illetve annak toString() metódusa által
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 45/80
visszaadott karaktersorozatot) Ha a szam karaktersort adjuk meg paraméterként,akkor a program megpróbálja az adott argumentumot double típusú számmákonvertálni (Double.parseDouble(String)) Mivel ez nem sikerülhet, egy
NumberFormatException jön létre, amelyet szintén lekezelünk. Az eredmény akivételobjektum String-reprezentációjának kiírása a képernyőre. Ha az exceptionszót adjuk meg, akkor egy általunk kiváltott kivétel jön létre. Ehhez a kivételobjektumok ősosztályát, az Exception osztályt használjuk. Az ismeretlen szótmegadva paraméterül szintén egy Exception-t váltunk ki, de ennek egy másikkonstruktorát használva. Ez a konstruktor a paraméterként kapott String objektumotüzenetként elmenti, s azt a getMessage() metódushívásra válaszként visszaadja.Elkapott Exception objektumok esetén a printStackTrace() metódust használjuk,amely egy hívási fát ír a képernyőre, amely megmutatja, hogy mely metódus okozottkivételes programállapotot, s az adott metódust ki hívta (mely forrásfile melyik sora).Ezt a hívási fát visszavezeti a main metódusig, egyszer ű debug információtszolgáltatva ezzel. Ha más argumentumot adunk meg, akkor a „Nincs kivétel”mondat íródik a képernyőre.
A példában található még egy finally ág is. Ez az ág a catch ágakkal egy szintenadható meg (megadása opcionális, de ha szerepel, akkor mindig az utolsó catch utánkell állnia). Ebben az ágban olyan kódsorozatot rögzíthetünk, amely minden esetbenlefut: akkor is, ha a program végrehajtása során történt valami kivételes esemény, sakkor is, ha hiba nélkül mentek le az utasítások.
6.3. „ Saját” kivételek létrehozása, kiváltása és lekezelése
A Java kivételkezelése nyitott, ami azt jelenti, hogy bárki létrehozhat azízlésének megfelelő névvel és funkcionalitással ellátott kivételosztályokat, s példányosítva őket, kivételobjektumokat. Az egyetlen megkötés, hogy az adottosztálynak implementálnia kell a Throwable interfészt, de a szolgáltatásokmaximális kihasználtsága miatt célszer ű bb az Exception osztályból származtatni (haez lehetséges)
A Példa 6.4 a klasszikus verem adatszerkezet megvalósítása, ahol kihasználjuka kivételkezelés nyújtotta előnyöket, úgymint a saját kivételosztály definiálása,valamint a kivételek továbbdelegálása. A verem adatszerkezet két fontos metódus
tartalmaz: a pop()-ot, illetve a push(Object)-t, amelyek rendre a legfelső elemkivételét, valamint egy új elem verembe helyezését valósítják meg. A példában egyelem kivételének kísérletekor, üres verem setén egy UresVeremException, míg egyelem berakásakor, teli verem esetén egy TeleVeremException váltódik ki. (A veremmérete a konstruktor paramétereként adott, s futás alatt nem változtatható) Azt, hogya fent említett kivételek kiváltódásakor mit kell tenni, a verem felhasználója dönti el,de a Java kivétel-kezelési mechanizmusának köszönhetően mindenképpen fel kellkészülnie az eshetőségre.
A TeleVeremException konstruktora megkapja a betenni kívánt elemet,
amelyet kérésre vissza is tud adni, így biztosítva könnyebb tájékozódást a veremfelhasználójának.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 46/80
Példa 6.2 Egy egyszer ű kivételosztály forráskódjapubl i c cl ass Ur esVer emExcept i on ext ends Except i on{}
Példa 6.3 Egy összetettebb kivétel osztálypubl i c cl ass Tel eVer emExcept i on ext ends Except i on{
pr i vat e Obj ect dat a;
publ i c Tel eVeremExcept i on( Obj ect data){t hi s. dat a = dat a;
}
publ i c Obj ect get Dat a( ) {r et ur n dat a;
}publ i c St r i ng get Message( ) {
r et ur n „A ver embe nem si ker ul t bet enni a( z) ” +
dat a. t oSt r i ng( ) + „- t ! ”}}
Példa 6.4 Saját kivételek használatapubl i c cl ass Ver em{
publ i c f i nal i nt MERET; / / A ver em mér et epr i vat e i nt akt ual i s; / / A követ kező ür es hel y i ndexepr i vat e Obj ect [ ] t ar ol o; / / A ver em el emei t t ár ol ó t ömb
/ / A ver em mérete a konst r ukt or paramétereként megadható
publ i c Ver em( i nt mer et ) {MERET = mer et ;t arol o = new Obj ect [ MERET] ;
}/ / Ha nem adunk meg par amét erként egy méret et ,/ / akkor egy t í z el em t ár ol ásár a al kal mas ver em/ / j ön l ét r epubl i c Verem( ) {
t hi s (10) ;}
publ i c Obj ect pop( ) t hr ows Ur esVeremExcept i on{i f ( akt ual i s < 1)
t hr ow new Ur esVeremExcept i on( ) ;ret urn t arol o[ - - akt ual i s ] ;
}publ i c voi d push(Obj ect data) t hr ows Tel eVer emExcept i on{
i f ( akt ual i s == MERET)t hr ow new Tel eVeremExcept i on( data) ;
t ar ol o[ aktual i s++] = dat a;}
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 47/80
Példa 6.5 Saját kivételek elkapásapubl i c cl ass Ver emTeszt {
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {Verem verem = new Verem( 5) ;try{
/ / Az el ső ar gument umként megadot t St r i ng- et/ / számmá konver t ál j uk, í gy az oszt ál y más/ / ér t ék megadásával t eszt el het ő / / 0- r a Ur esVeremExcept i on, 5- nél nagyobb szám/ / esetén pedi g Tel eVer emExcept i on l ép f eli nt i nt er aci o = I nt eger . par seI nt ( ar gs[ 0] ) ;f or ( i nt i =0; i <i t er aci o, i ++)
ver em. push( new I nt eger ( i ) ) ;Obj ect ut ol so = ver em. pop( ) ;
}cat ch( Ur esVeremExcept i on uve){uve. pr i nt St ackTr ace( ) ;
}catch( Tel eVeremExcept i on t ve) {Syst em. out . pr i nt l n( t ve. get Message( ) ) ;}
}}
Zárszóként annyit, hogy a kivételkezelést lehet szeretni, nem szeretni, viszont bizonyos esetekben nem lehet megkerülni. Erre jó példa a következő fejezet,amelynek több megoldása is előírja számunkra a kivételek használatát, kezelését. Haegy helyen használnunk kell a kivételkezelés nyelvi elemeit, de ezt elmulasztjuk,akkor a fordító egy „unreported exception” hibaüzenettel tudatja velünk, hogy mi a
kötelességünk. Ez a hibaüzenet sok kezdő Java-programozónak megkeserítette máraz életét, s vette el kedvét a további tanulástól, de ha valaki egyszer megérti akoncepció lényegét, s ráérez használatának fontosságára és módjára, akkor egynagyon nagy lépést tett a valóban megbízható szoftverek fejlesztése felé.
7. I/O23 kezelés Java-ban
7.1. A csatorna (stream) fogalma, osztályozásai
Az egységes kezelhetőség érdekében a Java I/O kezelése a csatorna (stream)fogalma köré épül. A csatorna egy irányított adatfolyamként képzelhető el, amelynekvégén (irányától függően) egy adatforrás, vagy egy adatnyelő található. Ezeket acsatornákat a java.io csomagban található osztályok, s a belőlük képzett objektumokrepzerentálják.
A csatornákat három szempont szerint csoportosíthatjuk.o A csatorna iránya szerint beszélhetünk kimeneti és bemeneti csatornárólo Az adatfolyamon „közlekedő” adatok egységei alapján beszélhetünk
byte-, illetve karakterszervezésű csatornákrólo Attól függően, hogy az adott csatorna közvetlenül egy adatforrásra, vagy
más csatornákhoz további funkcionalitást adva egy már létező csatornára
23 Input/Output - Bemenet és kimenet
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 48/80
épül, beszélhetünk alapfunkciókat megvalósító csatornáról, vagy szűr ő csatornaobjektumról.
Az osztályok neveiből felismerhető az adott csatorna típusa. A byte szervezésű csatornák neve az irányától függően InputStream, ill. OutputStream utótagok kaptak.
(Az InputStream, illetve az OutputStream absztrakt osztályok ezen csatornák közösősei.) A karakterszervezésű csatornák alaposztályai, valamint a névkonvenciónakmegfelelő utótagjai a Reader (bemeneti oldalon), illetve a Writer (kimeneti oldalon).Az alapfunkciókat, ill. a szűr ő funkciókat megvalósító osztályokat a konstruktorukismeretében sorolhatjuk be. Az alapfunkciókat megvalósító osztályok konstruktorá-nak egy adatforrást, míg a szűr ők konstruktorának egy másik csatornát kell megad-nunk.
7.2. Alapfunkciók és szű r ő k
A java.lang csomag (5.2) esetén már említettük a System osztály három statikus
adattagját (System.out, System.in, System.err), amellyel az alapértelmezett I/Oeszközökhöz férhetünk hozzá. Ezek közül eddigi programjainkban a System.outadattagot használtuk ki. Ez egy kimeneti csatorna (PrintStream), amely lehetőséget
biztosít a képernyőre történő íráshoz.
Az alapfunkciókat biztosító csatornák, valamint a szűr ők felépítési lehetőségeités használatukat egy példaprogramon (Példa 7.1) keresztül szeretném bemutatni. Afeladat, hogy a billentyűzetr ől sorokat olvassunk be, majd az aktuálisan beolvasottsort fordított karaktersorrenddel kiírjuk a képernyőre.
Példa 7.1 A billentyű zet és a csatornák használatai mpor t j ava. i o. *;
publ i c cl ass For di t o{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
try{Buf f eredReader i n = new Buf f eredReader (
new I nput St r eamReader( Syst em. i n)) ;St r i ng s;whi l e( ! ( s = i n. r eadLi ne( ) ) . equal s( „Vege”) )
Syst em. out . pr i nt l n(new St r i ngBuf f er ( s) . r ever se( ) ) ;
} cat ch( I OExcept i on i oe) {System. out . pr i nt l n( „I / O hi ba l épet t f el ! ”);
}}
}
A program egy csomag (a már említett java.io) importálásával kezdődik. Ez acsomag tartalmazza az I/O műveletekhez elengedhetetlen osztályokat, interfészeket.Az I/O műveletek kivételt válthatnak ki (IOException), amelyet kezelnünk kell.
(Ilyen kivétel jelentkezhet például a csatorna adatforrásának meghibásodásakor) A bemeneti csatorna felépítése több lépésből tevődik össze. A feladat kiírása szerint
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 49/80
sorokat kell beolvasnunk, amelyet két különböző módon tehető meg. Az egyik, hogymindaddig olvassuk be a karaktereket, amíg sorvége jelet nem kapunk, majd ezutándolgozzuk fel a kapott információt. Ennél a megoldásnál azonban létezik egykényelmesebb is. Ez a BufferedReader szűr ő, amely egy karaktercsatornára épülveképes onnan egész sorok kiolvasására (readLine() metódus) A gond csak abbóladódhatna, hogy a System.in egy byte-os szervezésű bemeneti csatorna, aBufferedReader pedig karaktercsatornára tud ráépülni. A megoldást egy közéjükékelt InputStreamReader objektum adja.
A működés: A System.in alapértelmezett csatorna segítségével a billentyűzetr őladatokat olvashatunk be, amely byte-ok formájában adódik tovább. Ezeket a byte-okat az InputStreamReader karakterekké fogja össze. Az íly módon kapottkarakterekből a BufferedReader egy példányának readLine() metódusa állít összeteljes sorokat. (A BuffedReader readLine() metódusa mindaddig hívja azInputStreamReader read() metódusát, amíg sorvége jelet nem érzékel, majd az ígymegkapott karakterekből egy String objektumot állít elő. A InputStreamReaderread() metódusa az alatta levő InputStream read() metódusát hívja, s az ígymegkapott byte-okból páronként egy karaktert állít össze.)
A beolvasott szöveg megfordításához a StringBuffer reverse() metódusáthasználhatjuk. A program mindaddig várja a következő megfordítandó sort, amíg azmeg nem egyezik a „Vege” karaktersorozattal.
Természetesen a BufferedReader-en és az InputStreamReader-en kívül léteznekmás szűr ők is. Ezek közül néhánnyal találkozni fogunk a további példáink során, de
a terjedelmi korlátok miatt nem mutatható be mind. A szűr ők és szolgáltatásaikmélyebb tanulmányozásához lásd a http://java.sun.com/docs weboldalon találhatódokumentumokat, valamint a java.io csomag javadoc által készített dokumentációját.
7.3. Kapcsolat a file-rendszerrel
A be- és kimenet kezelésének tárgyalásakor nem mehetünk el szó nélkül a Javafile-kezelése mellett, amely szorosan illeszkedik ebbe a témakörbe. A komolyabb
programok többsége használ valamilyen formában file-okat, ezért azok kezelésénekismerete kihagyhatatlan egy Java-fejlesztő kelléktárából.
A szoros kapcsolatot jelzi, hogy a könyvtárszerkezet file-jait és könyvtáraitreprezentáló File osztály szintén a java.io csomag része. A File osztály használatáhoznézzük a Példa 7.2-t. Az itt bemutatott példa egy paraméterként megadott file (vagykönyvtár) adatait listázza a képernyőre. (Természetesen csak akkor, ha a paraméter-ként megadott file létezik.)
Megj.: A lastModified egy számot ad vissza, amely az 1970. január 1-jétől azutolsó módosítás dátumáig eltelt időintervallumot adja meg ezredmásodpercben.Ennek emberi „fogyasztásra” való átalakításához lásd a java.util.Date osztályt. (5.3.
alfejezet)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 50/80
Példa 7.2 Egy file adatainak képernyő re listázásai mpor t j ava. i o. Fi l e;
publ i c cl ass Fi l eDat a{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
try{Fi l e f i l e = new Fi l e( ar gs[0] ) ;i f ( f i l e. exi st s( ) ) {
pr i nt Fi l eDat a( f i l e) ;} el se {
Syst em. out . pr i nt l n( „A megadot t f i l e neml ét ezi k”) ;
}} cat ch( Except i on e) {
hasznal at ( ) ;}
}publ i c st at i c voi d hasznal at ( ) {Syst em. out . pr i nt l n( „Fi l eDat a filename” ) ;
}publ i c stat i c voi d pr i nt Fi l eDat a( Fi l e f ) {
Syst em. out . pr i nt l n(„Absol ut e pat h: ” + f . get Absol ut ePat h( ) + „\ n” +„Can r ead: ” + f . canRead( ) + „\ n” +„Can wr i t e: ” + f . canWr i t e( ) + „\ n” +„getName: ” + f . getName( ) + „\ n” +„get Par ent : ” + f . get Par ent ( ) + „\ n” +
„get Pat h: ” + f . get Pat h( ) + „\ n” +„l engt h: ” + f . l engt h( ) + „\ n” +„Last modi f i ed: ” + f . l ast Modi f i ed( ) ) ;
i f ( f . i sFi l e( ) )Syst em. out . pr i nt l n( „Ez egy f i l e”) ;
el se i f ( f . i sDi rect ory( ) )Syst em. out . pr i nt l n( „Ez egy könyvt ár ”) ;
}}
Természetesen a file-okról nem csak adatokat jeleníthetünk meg, hanem
hozzáférhetünk tartalmához, sőt módosíthatjuk is azt. Ehhez a I/O csatornákadatforrásaként, illetve adatnyelő jeként a felhasználni kívánt File típusó objektumot
kell megadnunk. Ilyen csatornák a FileInputStream, a FileOutputStream, aFileReader, valamint a FileWriter, amelyekhez az eddig bemutatott módonkapcsolhatjuk a már megismert, illetve a java.io csomag további szűr őit. A Példa 7.3 file másolását mutatja be, mégpedig oly módon, hogy az első paraméterben megadottfile-t másolja a második paraméterben megadott könyvtárba, s az újonnan létrehozottfile-nak a harmadik paraméterben megadott nevet adja. (A programban használtuk aFile osztály mkdirs() metódusát, amely egy megadott könyvtárat hoz létre,szülőkönyvtárakkal együtt, ha az szükséges. Az available() metódus a file végéig
még hátralévő byte-ok számát adja meg)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 51/80
Példa 7.3 File másolása megadott helyre és névveli mpor t j ava. i o. *;
publ i c cl ass Masol o{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
Fi l e sour ce = new Fi l e( ar gs[ 0] ) ;Syst em. out . pr i nt l n( sour ce. get Absol ut eFi l e( ) ) ;Fi l e dest Di r = new Fi l e( ar gs[ 1] ) ;i f ( ! destDi r . exi sts( ) ) destDi r . mkdi rs( ) ;Fi l e dest = new Fi l e( dest Di r , ar gs[ 2] ) ;Syst em. out . pr i nt l n( dest . get Absol ut eFi l e( ) ; ) ;masol ( sour ce, dest ) ;
}publ i c st at i c voi d masol ( Fi l e sour ce, Fi l e dest )
t hr ows I OExcept i on{Fi l eI nput St r eam i n = new Fi l eI nput St r eam( sour ce) ;
Fi l eOut put St r eam out = new Fi l eOut put St r eam( dest ) ;whi l e( i n. avai l abl e( ) ! = 0) out . wr i t e( i n. read( ) ) ;i n. cl ose( ) ;out . f l ush( ) ; out . cl ose( ) ;
}}
7.4. Szerializáció
A fejezet eddigi programjai csak primitív típusok csatornára írására, illetvecsatornából történő olvasására voltak képesek. Természetesen mód van objektumok
írására és olvasására is. Ezt a mechanizmust szerializációnak nevezzük. A gyakorlatihasznosság érzékeltetésére gondoljuk végig, hogy mi történne, ha nem lennénkképesek az objektumok aktuális állapotának háttértárolóra, vagy valamely máshosszabb élettartamú tárolóhelyre menteni. Például egy banki alkalmazás mindenleállításkor, vagy újraindításkor elvesztené az ügyfelekr ől, valamint a számlákróltárolt adatait. (Eddig programjaink során az adatok a memóriában tárolódtak, amelyminden programbefejeződés után törlődött.) Természetesen a problémát úgy is meglehetne oldani, hogy primitív típusú értékekként kiírjuk az objektumok adattagjaitegy file-ba, de bonyolultabb osztálystruktúrák esetén (amikor az adattagok isobjektumok) ez nagyon sok vesződséggel járna. Ezt a terhet veszi le a vállunkról a
szerializáció.
A megvalósításhoz a csatornán keresztül kezelendő objektum osztályának megkell valósítania a java.io.Serializable interfészt (Példa 7.4), amely nem ír elő újabbmetódus-deklarációt az osztály számára, csak jelzi, hogy jogunk van az adottosztályba tartozó (illetve az adott osztályból származtatott típusú) objektumokcsatornára írására.
Objektumok olvasására, illetve írására az ObjectInputStream, valamint azObjectOutputStream szűr őosztály használható, amelyek rendelkeznek egy
readObject(), illetve egy writeObject(Object) metódussal (Példa 7.5). AwriteObject(Object) a paraméterként megadott objektum adattagjain rekurzívan
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 52/80
végigmegy, s kiírja azokat a csatornára (egy azonosító, egy név, valamint egy értékhármasaként) Csak az adattagok kerülnek kiírásra, a metódusok kódja nem, ezértvisszaolvasáskor az olvasó programnak rendelkeznie kell az adott osztálydefiníciójával ahhoz, hogy a művelet sikeres legyen. Ha azt szeretnénk, hogy egyadott adattag ne kerüljön kiírásra, használjuk a transient módosítót. Az objektumcsatornáról történő olvasásához használjuk a readObject() metódust. Ez az általánosműködőképesség miatt Object típusú objektummal tér vissza, amelyet nekünk kell amegfelelő típusra cast-olni. (Példa 7.5)
Példa 7.4 Szerializálható osztály definíciójai mpor t j ava. i o. Ser i al i zabl e;
publ i c cl ass I mmor t al i mpl ement s Ser i al i zabl e{i nt er t ek;St r i ng nev;
publ i c I mmor t al ( ) {t hi s. er t ek = 10; t hi s. nev = „Ez a neve”;}publ i c voi d set Er t ek( i nt er t ek) { t hi s. er t ek = er t ek; }publ i c voi d set Nev(St r i ng nev){ t hi s. nev = nev; }publ i c St r i ng t oSt r i ng( ) {
r etur n „neve: ” + nev + „, er t eke: ” +I nt eger . t oSt r i ng( er t ek) ;
}}
Példa 7.5 Objektum file-ba írása, s visszaolvasása (szerializáció)i mpor t j ava. i o. *;
publ i c cl ass I mmort al Demo{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) t hr ows Except i on{
I mmor t al f i r st = new I mmor t al ( ) ;System. out . pr i nt l n( f i r st) ;Fi l e dest = new Fi l e( „Obj ect Saver . dat ”) ;i f ( ! dest . exi sts( ) ) dest . creat eNewFi l e( ) ;f i r st . set Nev( „Mas a neve”) ; Syst em. out . pr i nt l n( f i r st ) ;Obj ect Out putSt r eam oos = new Obj ect Out putSt r eam(
new Fi l eOut put St r eam( dest ) ) ;oos. wr i t eObj ect ( f i rst ) ;f i r st . set Er t ek( 15) ; f i r st . set Nev( „Nev”) ;System. out . pr i nt l n( f i r st) ;Obj ect I nput St r eam oi s = new Obj ect I nput St r eam(
new Fi l eI nput St r eam( dest ) ) ;I mmor t al second = ( I mmor t al ) oi s. r eadObj ect ( ) ;Syst em. out . pr i nt l n( second) ;
}}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 53/80
8. Párhuzamos programozás
Eddigi programjaink során a szekvencia volt a legsűr ű bben használt vezérlésiszerkezet, ennek következtében a leírt programsorok (fordítás után) a leírásuksorrendjében hajtódtak végre. Egy adott kódrészletnek mindig meg kellett várnia az
őt megelőző kódrészletek végrehajtását. A programok többsége futási idejénektöbbségét I/O műveletekkel tölti, ezért a processzor kihasználtságának szempontjábólnem ideális, ha a parancssoroknak mindig meg kell várnia az előtte lévő utasításokvégrehajtását (az I/O műveletek nem használják processzort, így annak műveletikapacitása az I/O alatt kihasználatlan marad). Ennek a problémának a megoldásárafejlesztették ki a párhuzamos programozás elméletét, amely lehetővé teszi több
parancs „egymás melletti”, „egymással párhuzamos” futtatását.
8.1. A párhuzamos programozás elmélete, elő nyei
Szekvenciális végrehajtású programok esetén egy idő ben csak egy folyamat(utasítássor) szeretné utasításainak végrehajtását, s mindaddig, amíg ezek azutasítások nem fejeződtek be, blokkolja az er őforrásokat (közöttük a processzort is)Ennek szemléltetésére nézzük az Ábra 8-1-t, amely három fogyamat processzorrakerülését szemlélteti az idő függvényében. Ebben az esetben a második illetve aharmadik folyamat megvárja, amíg az előtte lévők befejezik futásukat.
Ábra 8-1 Szekvenciális végrehajtású utasítások processzorhasználata
Párhuzamos utasítás-végrehajtás esetén több folyamat verseng a processzorért,s egy úgynevezett ütemező dönti el, hogy aktuálisan melyik folyamat használhatja azer őforrást. Általános megvalósítás, hogy egy egységnyi időt a folyamatok számának
megfelelően időszeletekre osztanak, s minden folyamat csak egy időszeletet kap avégrehajtásra. Ha ennyi idő nem elegendő, akkor újból beáll a sor végére, svárakozik a következő időszeletére. Ha az időegységet sikerül jól megválasztani,akkor úgy tűnik, mintha a folyamatok egyszerre használnák a processzort. (Ehelyettcsak sűr űn váltják egymást a processzoron.) A működést az Ábra 8-2 szemlélteti. Afolyamatok gyorsabb lefutása abból adódik, hogy I/O művelet esetén az adottfolyamat addig nem kér processzoridőt, amíg az I/O-t be nem fejezte24, s nem
blokkolja a többieket.
24 Az ábra diagrammjának közepén a második folyamat futása felfüggesztődik. Ez a leállás feleltethető meg azI/O műveletnek.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 54/80
Ábra 8-2 Párhuzamos végrehajtású utasítások processzorhasználata
8.2. Szálak állapotai, életciklusa
A párhuzamosan futó folyamatok párhuzamosan futó programokat takarnak,viszont ez a párhuzamosság megvalósítható programon belül is. Erre használhatóak a
szálak, amelyek ugyanúgy működnek a programokon belül, mint a párhuzamosfolyamatok az operációs rendszer szemszögéből., tehát az elő bbi pontban megadottkét ábra rájuk is értelmezhető. A szálak végrehajtásuk során több állapotátmenetenmehetnek keresztül. A fontosabb állapotokat, s a közöttük lévő átmeneteket az ábraszemlélteti.
Ábra 8-3 Szálak állapotátmenetei
Ha elindítunk egy szálat, akkor az a futásra kész állapotba kerül, amely azt jelenti, hogy kész utasításainak feldolgoztatására. Ekkor vár az ütemezőre, amely
elő bb-utóbb kiosztja számára a processzort. Amint elérkezett az ő időszelete, a processzor elkezdi feldolgozni az utasításait. Ezt az állapotot nevezzük futóállapotnak. Ha sikerült az összes utasítást végrehajtatni, akkor a szál a halottállapotba kerül, vagyis befejezi működését. Ha nem sikerül elvégezni a kitűzöttfeladatokat, akkor az ütemező visszaállíthatja futásra kész állapotba, helyet és időtadva ezzel másoknak a futásra. Ha egy futó szálnak valamilyen más er őforrásra vanszüksége (például egy I/O művelet miatt), akkor szintén elhagyhatja a futó állapotot,s az úgynevezett blokkolt állapotba kerül. A blokkolódást okozó műveletek
befejezésekor (pl. I/O vége) a szál ismét beáll a processzorra várakozók sorába, smindaddig a futásra kész állapotban marad, amíg az ütemező processzorra nem
juttatja. Ez a körforgás addig tart, amíg el nem éri a halott állapotot.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 55/80
8.3. Szálak kezelése, szinkronizálás Java-ban
A Java keretein belül a szál egy futásra képes objektumként fogható fel.Definiálására két lehetőség van (Példa 8.1). Az alapvető különbségek a két megoldásközött abból adódnak, hogy az egyik egy öröklés (a Thread osztályból), annak
minden előnyével és hátrányával, míg a másik egy interfész (a Runnable)implementálása, szintén annak minden előnyével és hátrányával (Példa 8.1). Ebbőlkövetkezőleg az öröklésnél használhatjuk az ős osztály metódusait (ilyen a példábana getName() metódus), viszont nem adhatunk meg újabb őst osztályunknak (Csakegyszeres öröklés lehetséges!). Ezzel szemben az interfész megvalósítása objektum-orientáltabb technika, valamint nem zárja ki a más osztályból történő öröklést. AThread osztálynak van egy statikus metódusa, amely az éppen aktuálisan futó szálobjektumot adja vissza (currentThread()), s ennek segítségével már megoldhatóinterfész-megvalósítás esetén is a Thread osztály szolgáltatásainak kihasználása.
Egy szálat mindig a start() metódusának meghívásával indíthatunk el. Ez ametódus elvégzi az operációs rendszer felé a natív hívásokat (fizikailag is létrehozzaa szálat), majd elkezdi végrehajtani a run() metódusban megadott utasításokat. ARunnable implementálása esetén nem áll rendelkezésünkre egy megfelelő adminisztrációt végző start() metódus, ezért az ily módon definiált szálunkfuttatásához be kell őt „csomagolnunk” egy Thread osztályba (annak megfelelő konstruktorát használva - Példa 8.1)
Példa 8.1 Szál létrehozása és indítása25 publ i c cl ass El soPel da{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {Saj at Szal 1 el so = new Saj at Szal 1( ) ;Saj atSzal 2 masodi k = new Saj at Szal 2( ) ; Thread t hread = new Thr ead( masodi k) ;el so. star t ( ) ;t hread. start ( ) ;}
}
cl ass Saj at Szal 1 extends Thr ead{publ i c voi d r un( ) {
Syst em. out . pr i nt l n( "A f ut ó szál : " + get Name( ) ) ;}}
cl ass Saj atSzal 2 i mpl ement s Runnabl e{publ i c voi d r un( ) {
Syst em. out . pr i nt l n( "A f ut ó szál : " + Thread. cur r entThread( ) . getName( ) ) ;
}}
25
Egy file-ban definiálható több osztály is, de ezek közül csak egy lehet public módosítóval ellátva, s ennekneve meg kell hogy egyezzen a file nevével. Ezt kihasználva a bemutatott példa ElsoPelda.java névenelmenthető, majd fordítható és futtatható.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 56/80
A Példa 8.2 azt mutatja meg, hogy hogyan lehet egy szálat várakoztatnimindaddig, amíg egy másik szál be nem fejezi munkáját. Erre a join() metódushasználható. Ekkor az aktuális szál mindaddig felfüggeszti futását (blokkoltállapotba kerül), amíg a join() metódus tulajdonosa végre nem hajtatta a run()metódusában szereplő utasításokat. A könnyebb érthetőség érdekében érdemesmegnézni a join() metódus törlése után kapott forrás futásának eredményét. (Asleep() metódus az adott szálat blokkolt állapotban helyezi a paraméterben megadottidőre, amelyet ezredmásodpercekben kell érteni. Jelen esetben csak aszemléletességet szolgálja, így ugyanis szembeötlő bb a különbség a join()használata, illetve mellőzése között.) Ennél a programnál már nem úszhatjuk meg akivételkezelést ( InterruptedException)
Példa 8.2 Szálak összekapcsolásapubl i c cl ass J oi nPel da{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
Saj at Szal 3 el so = new Saj at Szal 3( ) ;Saj at Szal 4 masodi k = new Saj at Szal 4( el so) ;System. out . pr i nt l n( " I ndi t om a szal akat . . . " ) ;el so. star t ( ) ;masodi k. st ar t ( ) ;
}}
cl ass Saj at Szal 4 extends Thr ead{pr i vat e Thr ead wai t 4me;
publ i c Saj at Szal 4( Thr ead masi k) {super ( ) ;wai t 4me = masi k;
}publ i c voi d r un( ) {
Syst em. out . pr i nt l n( getName( ) + " var " +wai t 4me. get Name( ) + " - r a. . . " ) ;
/ / Ez a t r y- cat ch bl okk t ör öl het ő a kül önbségek/ / szeml él t et ése ér dekébentry{
wai t 4me. j oi n( ) ;
}cat ch( I nt er r upt edExcept i on i e) {}Syst em. out . pr i nt l n( wai t 4me. get Name( ) + " bef ej ezt e
f ut asat . " ) ;f or ( i nt i =0; i <5; i ++) {
try{sl eep( 500) ;
}cat ch( I nt er r upt edExcept i on i e) {}Syst em. out . pr i nt l n ( "Udvozl et " + get Name( ) + " -
t ol " ) ;}
}
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 57/80
cl ass Saj at Szal 3 extends Thr ead{publ i c voi d r un( ) {
Syst em. out . pr i nt l n( get Name( ) + " f ut . . . ") ;f or ( i nt i =0; i <5; i ++) {
try{
sl eep( 500) ;}cat ch( I nt er r upt edExcept i on i e) {}Syst em. out . pr i nt l n ( "Udvozl et " + get Name( ) + " -t o l " ) ;
}}
}
A Thread osztály további hasznos szolgáltatásainak egyike a prioritásállíthatóságának biztosítása. A prioritás fontosságot jelent, amelynek megvalósításaoperációs rendszertől függhet. Bizonyos operációs rendszerek a prioritás arányában
adnak időszeletet a futó szálaknak (a nagyobb prioritású szál nagyobb szeletet kap azidőegységből), míg bizonyos rendszerek esetén csak a legmagasabb prioritású szálak
futnak egymással párhuzamosan, az alacsonyabb értékkel rendelkezők pedig várnakmindaddig, amíg a fontosabb folyamatok be nem fejeződnek. A Java kilenckülönböző prioritási szintet különböztet meg, ezeket egy-egy egész számmal jelölve.A minimális (Thread.MIN_PRIORITY), a maximális (Thread.MAX_PRIORITY),valamint a normális (Thread.NORM_PRIORITY) érték azonosítására konstans áll arendelkezésünkre. A prioritást a setPriority() metódussal állíthatjuk be, illetve agetPriority() metódussal kérhetjük le. (Példa 8.3)
Szükség lehet még egy futó szál megszakítására is, amelyet az interrupt() metódushívással érhetünk el. Ennek a megszakítási kérelemnek az ellenőrzésére azisInterrupted() metódus használható (Példa 8.3). Arra a kérdésre, hogy egy szál fut-e,az isAlive() metódus adja meg a választ. Fontos lehet még a yield() metódushasználata, amely akkor előnyös, ha nem vagyunk biztosak abban, hogy a futtatórendszer milyen ütemezési technikát alkalmaz. Ezzel a metódussal a szál önkéntáthelyezi magát a futó állapotból a futásra kész állapotba, így biztosítva másokszámára a processzorra kerülés lehetőségét.(Példa 8.3)
Példa 8.3 Szálak használatának lehet ő ségei26 i mpor t j ava. i o. *;
publ i c cl ass Pr i or i t asPel da{publ i c st at i c voi d mai n( St r i ng[ ] ar gs) t hr ows Except i on{
Fi l e out put = new Fi l e( "out put . t xt ") ;i f ( ! out put . exi st s() ) out put . creat eNewFi l e( ) ;Pr i nt St r eam out = new Pr i nt St r eam(
new Fi l eOut put St r eam( out put ) ) ;System. set Out ( out ) ; Thread el so = new Teszt Szal ( "El so") ;
26
A példában a ystem.setOut() metódushívással átirányítottuk az alapértelmezett kimenetet egy file-ba, így tévekönnyebbé az eredmény áttekintését. A sleep() metódusok 2 ezredmásodpercre altatják el az aktuális szálat. Ezaz érték néhány architektúrán kevés lehet, növelésével lehet kisérletezni a kívánt eredmény eléréséig.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 58/80
Thr ead masodi k = new Teszt Szal ( "Masodi k") ; Thread harmadi k = new Teszt Szal ( "Har madi k" ) ; Thread. cur r entThread( ) . set Pr i or i t y( Thread. MAX_PRI ORI TY) ;System. out . pr i nt l n ( " I ndi t j uk a szal akat . . . " ) ;el so. star t ( ) ;
masodi k. st ar t ( ) ;har madi k. st ar t ( ) ;try{
Thread. cur r entThread( ) . sl eep( 2) ;} cat ch( I nt er r upt edExcept i on i e) {}Syst em. out . pr i nt l n ( "Az masodi k szal pr i or i t asanak
novel ese. . . ") ;masodi k. set Pr i or i t y( masodi k. get Pr i or i t y( ) + 2) ;try{
Thread. cur r entThread( ) . sl eep( 2) ;} cat ch( I nt er r upt edExcept i on i e) {}
Syst em. out . pr i nt l n ( "Az masodi k szal pr i or i t asanakcsokkent ese. . . ") ;masodi k. set Pr i or i t y( masodi k. get Pr i or i t y( ) - 4) ;try{
Thread. cur r entThread( ) . sl eep( 2) ;} cat ch( I nt er r upt edExcept i on i e) {}Syst em. out . pr i nt l n ( "A pr i or i t asok egyenl ove
t et el e. . . " ) ;masodi k. set Pr i or i t y( masodi k. get Pr i or i t y( ) + 2) ;try{
Thread. cur r entThread( ) . sl eep( 2) ;
} cat ch( I nt er r upt edExcept i on i e) {}System. out . pr i nt l n ( "Szal ak l eal l i t asa. . . ") ;el so. i nt er r upt ( ) ;masodi k. i nt er r upt ( ) ;har madi k. i nt er r upt ( ) ;out . f l ush( ) ; out . cl ose( ) ;
}}
cl ass Teszt Szal ext ends Thr ead{publ i c Teszt Szal ( St r i ng nev) {
super ( nev) ;}publ i c voi d r un( ) {
whi l e( t r ue) {Syst em. out . pr i nt l n ( get Name( ) + ": f ut . ") ;i f ( i s I nt er rupt ed( ) ) break;yi el d( ) ;
}}
}
A szálak használat során felmerülhetnek bizonyos komplikációk abbólkifolyólag, hogy előfordulhat, hogy egy adatot egyszerre több szál is módosít, egy
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 59/80
metódust egyszerre több szál is futtat. Például egy verem adattípus elembehelyezésekét műveletből állhat. Az egyik növeli az aktuális veremmutatót, a másik pedig amutató által jelölt helyre beteszi a betenni kívánt elemet. Ha ezt a műveletet két szálegymással párhuzamosan végzi el ugyanazon a vermen, akkor mindkettő növelieggyel a mutató értékét (így az kettővel növekszik), majd ugyanarra a helyremindkettő beteszi az általa kívánt elemet. Ez lyukat eredményez a veremben (egyhelyet átugrottak), valamint a két elem közül csak a késő bbi marad meg. Az ilyenhibák kiküszöbölésére alkották meg a szinkronizálás lehetőségét, amely többműveletet egyetlen elemi műveletté fog össze, így biztosítva, hogy egyszerre csakegy szál futtathassa. Ha egy metódusban szereplő összes utasítást egyetlen elemiműveletként szeretnénk végrehajtatni, akkor a synchronized módosítót kellhasználnunk a metódus fejlécében (Példa 8.4). Lehetőség van egy blokkszinkronizálására is. Ezt a
synchr oni zed( objektum) {utasítások
} blokképzéssel tehetjük meg, ahol objektumként azt az objektumot kell megadnunk,amelyet meg akarunk védeni más szálak hozzáférésétől. (A többi szál, amelynekszüksége van az adott objektumra, mindaddig várakozik, amíg az adott blokk le nemfut.)
Többprocesszoros gépeken történő fejlesztés és futtatás esetén lehet szükség avolatile módosítóra, amely lehetővé teszi, hogy egy adott változó értéke mindig amemóriában tárolódjon. Ha ezt nem használjuk, akkor abból adódik a gond, hogy agyorsabb elérés érdekében bizonyos rendszerek néhány változó értékét a processzor
regisztereiben tárolnak, így azokhoz a másik processzor nem férhet hozzá. (Esetlegegy régebbi állapotát látja a változónak.)
Példa 8.4 Metódus szinkronizáslásapubl i c cl ass Thr eads{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) { Threads t = new Thr eads( ) ;Szal el so = new Szal ( t , "el so") ;Szal masodi k = new Szal ( t , "masodi k") ;el so. star t ( ) ;masodi k. st ar t ( ) ;
}publ i c synchr oni zed voi d met odus( ) t hr ows Except i on{
Syst em. out . pr i nt l n ( "El i ndul t a met odus. I ndi t ot t a: "+ Thr ead. cur r ent Thr ead( ) ) ;
f or ( i nt i =0; i <10; i ++) { Thread. cur r entThread( ) . sl eep( 1000) ;Syst em. out . pr i nt l n ( Thr ead. cur r ent Thr ead( ) + "
mondj a: i = " + i ) ;}Syst em. out . pr i nt l n ( "A met odus l eal l . Akt ual i s szal : "
+ Thr ead. cur r ent Thr ead( ) ) ;}
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 60/80
cl ass Szal ext ends Thr ead{St r i ng nev; Threads t ar get ;
publ i c Szal ( Thr eads t ar get , St r i ng nev) {
t hi s. nev = nev;t hi s. t ar get = t ar get ;}publ i c voi d r un( ) {
try{t ar get . met odus( ) ;
}cat ch( Except i on e) {e. pr i nt St ackTr ace( Syst em. er r ) ;
}}publ i c St r i ng t oSt r i ng( ) {
r et ur n nev;}}
A szálak további lehetőségeinek kihasználása érdekében ajánlott a SUN oldalán(http://www.sun.com/docs) található dokumentációk böngészése.
9. Hálózati alkalmazások készítése
A Java-t életre hívó Sun alapfilozófiáinak egyike, hogy a hálózat maga aszámítógép. Ebből következőleg nagyon sok energiát fordítottak a hálózati
fejlesztések minél magasabb szintű
támogatására, s ennek hatása érződik a Javatechnológián is. Ha egy szoftverfejlesztő tisztában van a nyelv alapelemeivel
(különös tekintettel az I/O kezelésre), akkor nagyon egyszer űen készíthet hálózatosalkalmazásokat. A többszálú programok írásának nyelvi támogatása pedig lehetővéteszi, hogy ezek a programok ne csak könnyen elkészíthetőek, de hatékonyak islegyenek. Terjedelmi korlátok miatt nem tudunk bemutatni minden lehetőséget, de afejezet célja, hogy biztosítson egy bizonyos szintű rálátást a lehetőségekre, valamint
bemutasson egy több kliens együttes kezelését biztosító szerver-kliens alkalmazást,amelyet ezután mindenki könnyen adoptálhat saját problémájának hálózatonkeresztüli megoldására.
9.1. Összeköttetés alapú, és összeköttetésmentes hálózati modell
A hálózatba kapcsolt számítógépeknek a hálózati alkalmazás nyújtotta előnyökkihasználása érdekében kommunikálniuk kell egymással. Ennek a kommunikációnakkét alapvetően eltér ő típusát különböztethetjük meg attól függően, hogy akommunikációt meg kell-e előznie egy kapcsolatfelvételnek, vagy sem. Akapcsolatfelvételt igénylő kommunikációs modellt összeköttetés alapú, míg akapcsolatfelvétel nélkülit összeköttetés-mentes hálózati modellnek nevezzük. Egytalán szemléletes példával élve az összeköttetés alapú modellt a telefonáláshoz, azösszeköttetés-mentes pedig a postai levélküldéshez hasonlíthatjuk. A hálózati
kapcsolatban általában nem egyenrangú felek kommunikálnak; valakinekkezdeményeznie kell a hívást, valakinek pedig fogadnia kell a hívást, s válaszolni a
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 61/80
kezdeményező kérdéseire. Ezt a kapcsolattartási mód kliens-szerver architektúrakéntvonult be a köztudatba, ahol a kezdeményező fél (alkalmazás) a kliens, míg a fogadófél (alkalmazás) a szerver. A fejezet példájában egy összeköttetés alapú, kliensből ésszerverből álló alkalmazást készítünk.
9.2. A java.net csomag alkalmazása
9.2.1. Összeköttetés alapú szerver alkalmazás
Először létrehozunk egy szervert, amely a hozzá bejelentkező kliensektől egysornyi szöveget vár, majd visszaküldi ennek a sornak a fordítottját. A szerver első verzióját a Példa 9.1 tartalmazza.
Példa 9.1 Egy kliens kiszolgálására alkalmas szerveri mpor t j ava. net . *;i mpor t j ava. i o. *;
publ i c cl ass For di t oSzer ver {publ i c st at i c f i nal i nt PORT = 4105;publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
try{Server Socket szerver = new Server Socket ( PORT) ;System. out . pr i nt l n( "A szer ver f ut . . . ") ;Socket kl i ens = szer ver . accept ( ) ;Syst em. out . pr i nt l n( "Egy kl i ens j el ent kezet t ") ;ser vi ce( kl i ens) ;
}cat ch( I OExcept i on i oe) {
i oe. pr i nt St ackTr ace( Syst em. er r ) ;}
}pr i vat e st at i c voi d ser vi ce( Socket kl i ens)
t hr ows I OExcept i on{Buf f eredReader i n = new Buf f eredReader (
new I nput St r eamReader ( kl i ens. get I nput St r eam( ) ) ;St r i ng s = i n. r eadLi ne( ) ;Syst em. out . pr i nt l n( new St r i ngBuf f er ( s) . r ever se( ) ) ;Buf f er edWr i t er out = new Buf f eredWr i t er (
new Out put St r eamWr i t er ( kl i ens. get Out put St r eam( ) ) ;out . wr i t e( new St r i ngBuf f er ( s) . r ever se( ) ) ;out . newLi ne( ) ; out . f l ush( ) ;
}}
Az alkalmazás újdonságainak listája már az első sorban elkezdődik. Hálózatos programok írásához ugyanis használnunk kell a java.net csomagot. Ez a csomagtartalmazza az egyszer ű alkalmazáskészítéshez elengedhetetlen osztályokat. Ahálózatos programok filozófiája sokban támaszkodik az I/O kezelésre, hiszen az ottmegszokott módon csatornákat hozunk létre, amelyeken keresztül a már ismertetettmódon le tudjuk bonyolítani az adatcserét. A szerver elsődleges feladata, hogy portotfoglaljon, kérjen az operációs rendszertől. Ezen a porton azután megtalálják őt a
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 62/80
kliensek, s megkérhetik a szolgáltatásának elvégzésére. (Err ől még lesz szó a kliens bemutatásánál.) A szerver létrehozásához a ServerSocket osztályt kell használnunk,amely konstruktorában megadott porton várja a kliensek jelentkezését.
A ServerSocket osztály accept() metódusa használható arra, hogy programunkatmindaddig blokkoljuk, amíg egy kliens be nem jelentkezik a szervert futtató gépadott portjára. Ha ez a bejelentkezés megtörtént, akkor az említett metódus egySocket osztályú objektumot hoz létre, s ezzel az objektummal tér vissza. Ez azobjektum képviseli a kliensalkalmazást. S idáig eljutva már egyszer ű I/O kezelés azegész. A Socket típusú objektumtól, mint adatforrástól, illetve adatnyelőtőlelkérhetünk egy bemeneti valamint egy kimeneti csatornát, amely semmiben semkülönbözik az I/O fejezet alatt bemutatott csatornáktól, így akár szűr őket iskapcsolhatunk rájuk (getInputStream(), getOutputStream()). Ha a klienstől várunkadatot, akkor azt a bemeneti csatornájáról (InputStream) kell beolvasnunk, míg hainformációt akarunk vele közölni, akkor azt a kimeneti csatornájára kell juttatnunk.Ennyire egyszer ű az egész, a többit a Java elintézi helyettünk.
9.2.2. Kl iens alkalmazás a szerverhez
A kliens alkalmazás elkészítése sem sokkal bonyolultabb a szerver létrehozásá-nál. Egy lehetséges megvalósítást mutat a Példa 9.2.
Példa 9.2 Egy kliens alkalmazás a fordító szerverhezi mpor t j ava. net . *;i mpor t j ava. i o. *;
publ i c cl ass For di t oKl i ens{publ i c st at i c f i nal i nt PORT = 4105; 27 publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
try{Socket socket = new Socket ( args[ 0] , PORT) ;Buf f er edWr i t er out = new Buf f eredWr i t er (
new Out put St r eamWr i t er ( socket . getOut put St r eam( ) ) ;out . wr i t e( ar gs[ 1] ) ; out . newLi ne( ) ;out . f l ush( ) ;Syst em. out . pr i nt l n( "Az el kül döt t szöveg: „+ar gs[ 1] ) ;Buf f eredReader i n = new Buf f eredReader (
new I nput St r eamReader ( socket . get I nput St r eam( ) ) ;Syst em. out . pr i nt l n ( "Er edmény: " + i n. r eadLi ne( ) ) ;
}cat ch( UnknownHost Except i on uhe) {uhe. pr i nt St ackTr ace( Syst em. er r ) ;
}cat ch( I OExcept i on i oe) {i oe. pr i nt St ackTr ace( Syst em. er r ) ;
}}
}
27
A portot nem állíthatjuk be a ForditoSzerver.PORT alapján, hiszen ez az osztály nem feltétlenül létezik aklienst futtató számítógépen, viszont ügyelni kell arra, hogy a két végpontnál megadott port-azonosítómegegyezzen.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 63/80
A szerverrel kommunikálni képes kliens létrehozásához egy Socket típusúobjektumot kell létrehoznunk, amely konstruktorában megkapja, hogy melyik (hostnévvel vagy IP-címmel azonosított) számítógépen (ezt az azonosítót esetünkben azelső argumentum tartalmazza), s annak pontosan melyik portján kell a szervertkeresnie a kapcsolatfelvétel szándékával. Ezután a szervernél már bemutatott módonelkérjük a Socket típusú objektumtól a ki-, illetve a bemeneti csatornáit, s ezenkeresztül kommunikálhatunk a szerverünkkel. A kliens létrehozása során felléphetegy UnknownHostException kivétel, amely a nevéből adódóan arra figyelmeztet,hogy a megadott azonosító nem alkalmas a célszámítógép megtalálására.
A kliens egy lehetséges futtatási paraméterezése: java ForditoKliens localhost „Ezt forditsd”
A megadott parancssori utasítás a (már előre lefordított) kliensünket futtatja, s afuttatás környezetéül szolgáló számítógépen keresi a szervert. Ha a számítógépünkön
fut a szerveralkalmazás is (azt előzőleg el kell indítani), akkor a kliens képes akapcsolatfelvételre, s a második paraméterként megadott szöveget (Ezt fordítsd)elküldi a szervernek, amely remélhetőleg megfordítva küldi azt vissza.Természetesen a localhost helyett megadhatunk bármilyen host nevet, esetleg IP-címet, de ügyelnünk kell arra, hogy a megadott azonosító valóban egy elérhető számítógépet azonosítson, a az adott gépen fusson a szerver alkalmazás (Ellenkező esetekben kivételt vált ki a programunk, s nem végzi el a kért szolgáltatást.)
9.2.3. A szerver továbbfejlesztése
Az eddig használt szerverünk csak egy kliens kiszolgálására volt alkalmas,ezért minden kiszolgálás után újra kellett indítani. Természetesen nincs akadályaannak, hogy ezt a problémát kiküszöböljük. A legegyszer ű bb megoldás erre, hogy akliensre várakozó, valamint a klienst kiszolgáló kódrészletet egy végtelen ciklusbazárjuk (Példa 9.3), ezáltal biztosítva, hogy szerverünk ne álljon le a kívántnálhamarabb.
Példa 9.3 Több kliens soros kiszolgálása. . .Socket kl i ens;whi l e( t r ue) {
kl i ens = szer ver . accept ( ) ;Syst em. out . pr i nt l n( "Egy kl i ens j el ent kezet t ") ;servi ce( kl i ens) ;
}. . .
Egy ily módon létrehozott szerver leállítása csak valamilyen drasztikus módonvégezhető el, ezért érdemes továbbfejleszteni az alkalmazást, mégpedig oly módon,hogy a service() metódus egy logikai értéket adjon vissza, amely jelzi, hogy le kell eállítani a szervert. (A leállás feltétele bármi lehet - esetünkben például egy előremeghatározott karaktersor érkezése valamelyik klienstől.) Az ilyen szellembenmódosult kódrészletet a Példa 9.4 tartalmazza. A módosított service() metóduselkészítését az olvasóra bízzuk.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 64/80
Példa 9.4 Szerver, kliens által vezérelt leállással. . .Socket kl i ens;do{kl i ens = szer ver . accept ( ) ;
} whi l e( ser vi ce( kl i ens)) ;. . .
Az eddig elkészült szerverünk a kitűzött feladattal már remekül megbirkózik,viszont a valós szerverek nem mindig ilyen egyszer ű szolgáltatást végeznek.Előfordulhat, hosszabb szolgáltatások elvégzésére készített szerverek esetén, hogyegy bejelentkező kliensnek túl sokat kell várni az előtte érkezőkre, így csökken ahatékonyság. Az előző fejezet ismereteit felhasználva azonban ezt a problémát iskönnyen megoldhatjuk. Létre kell hoznunk egy olyan szálat, amely egy Socketobjektumot kap konstruktorának paramétereként, s ezzel az objektummallebonyolítja a szükséges kommunikációt. Ha szeretnénk megőrizni a kliens általi
vezérelhetőséget, akkor a szervert is át kell adnunk paraméterként a szálnak, amelyígy már tudja állítani azt a logikai változót, amely a szerver leállását biztosítja. Avégleges szervert a Példa 9.5 mutatja be.
Példa 9.5 Több kliens párhuzamos kiszolgálására alkalmas szerveri mpor t j ava. net . *;i mpor t j ava. i o. *;
publ i c cl ass For di t oSzer ver {publ i c st at i c f i nal i nt PORT = 4105;pr i vat e st at i c bool ean r unni ng = t r ue; 28
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {try{
Server Socket szerver = new Server Socket ( PORT) ;System. out . pr i nt l n( "A szer ver f ut . . . ") ;whi l e( r unni ng) {
Socket kl i ens = szer ver . accept ( ) ;Syst em. out . pr i nt l n( "Egy kl i ens j el ent kezet t " ) ; Thread t = new Ser vi ceThr ead( kl i ens, t hi s) ; 29 t . s t a r t ( ) ;
}}cat ch( I OExcept i on i oe) {i oe. pr i nt St ackTr ace( Syst em. er r ) ;
}}publ i c st at i c voi d st op( ) {
r unni ng = f al se;}
}
28 Mivel a szál objektum nem tud visszatérési értékkel szolgálni, fel kell venni egy logikai változót, amely azt
felügyeli, hogy kell-e még futnia a szervernek.29 A szálnak a feldolgozandó kliens melett át kell adni egy referenciát a szerverre vonatkozólag, hiszen csak így biztosított a szerver kliensen keresztüli leállíthatósága.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 65/80
cl ass Servi ceThr ead ext ends Thr ead{pr i vat e Socket kl i ens;pr i vat e For di t oSzer ver szer ver ;Ser vi ceThr ead( Socket kl i ens, For di t oSzer ver szer ver ) {
t hi s . kl i ens = kl i ens;
t hi s. szer ver = szer ver ;}publ i c voi d r un( ) {
try{Buf f eredReader i n = new Buf f eredReader (
new I nput St r eamReader ( kl i ens. get I nput St r eam( ) ) ;St r i ng s = i n. r eadLi ne( ) ;i f ( s. equal s(„Vege”) ) szer ver . stop( ) ;Syst em. out . pr i nt l n( new St r i ngBuf f er ( s) . r ever se( ) ) ;Buf f eredWr i t er out = new Buf f eredWr i t er(
new Out put St r eamWr i t er ( kl i ens. get Out put St r eam( ) ) ;
out . wr i t e( new St r i ngBuf f er ( s) . r ever se( ) ) ;out . newLi ne( ) ; out . f l ush( ) ;} cat ch( I OExcept i on i oe) {
i oe. pr i nt St ackTr ace( Syst em. er r ) ;}
}}
A szervert tovább optimalizálhatnánk oly módon, hogy nem konstruktorban,hanem egy metódus segítségével adnánk át a klienst a szálnak. Ilyen szálakbóllétrehoznánk egy listát, s elindítanánk őket. Egy kliens bejelentkezésekor csak abban
az esetben hoznánk létre újabb szálat, ha nincs a listában olyan, amely éppen nemcsinál semmit. Ellenkező esetben az éppen nem dolgozó szálnak adnánk át a bejelentkezett kliens. Ezzel a megoldással (valamint optimális listamérettel)megspórolhatnánk a szál létrehozásához szükséges idők nagy részét. A megvalósítástaz olvasóra bízzuk.
9.2.4. A java.net csomag további lehetőségei
A java.net csomag segítségével természetesen nem csak összeköttetés alapúkapcsolatot biztosíthatunk két alkalmazás között, hanem létezik osztály azösszeköttetés-mentes kapcsolat elérésére is. Ehhez egy DatagramPacket típusú
objektumot kell létrehoznunk, amelyet egy DatagramSocket tud eljuttatni acímzetthez. A hálózati címek objektum-orientáltabb szemléletű megvalósítását segítielő az InetAddress osztály, amely IP-címeket reprezentálhat. Az összetettebb url-ektámogatására az URL osztály hivatott, de könnyen tölthetünk le tartalmat url-lelmegadott címekr ől is az URLConnection osztály használatával, valamint ennekközvetlen leszármazottjával, a HttpURLConnection-nel. URL-ek használatakor nemárt ismerni a MalformedURLException kivételosztályt sem, amely akkor váltódik ki,hogyha egy megadott url rosszul van formázva (hiányzik a protokollazonosító...).Terjedelmi okok miatt ezeket az osztályokat nem áll módunkban bemutatni, de ezenhiányosság pótlására remekül alkalmas a Sun oldalain található dokumentációk
olvasgatása, az ott megadott példák kipróbálása.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 66/80
10. Eseményvezérelt fejlesztési modell
A Java grafikus elemeinek könnyebb elsajátításához elengedhetetlen azeseményvezérelt fejlesztési modell ismerete. Az eddigi tapasztalatok szerint a kezdő Java fejlesztők nehezen értik meg ezt a tervezési mintát, ezért mi egy külön fejezetet
szánunk rá.
10.1. Elméleti háttér
A szoftverek által modellezendő világokban sokszor előfordul, hogy bizonyosesemények bekövetkeztére végre kell hajtani a megfelelő kódrészleteket. Például egygomb lenyomása ilyen eseményként fogható fel, de esemény lehet az is, ha egyember mond valamit (a 3. fejezet Ember objektumának lefut a beszel() metódusa).Az ilyen jellegű problémák kezelésére alkalmas az eseményvezérelt fejlesztésiminta.
A tervezési minta középpontjában három szereplő áll. Az egyik maga azesemény (event). Ez egy olyan objektum, amely információkat tartalmaz a lezajlotteseményr ől. Például a megnyomott gomb feliratát, vagy a kimondott szövegcímzettjét. Emellett létezik egy (vagy több) eseményfigyelő (listener), amely egyadott eseménytípus bekövetkeztekor reagál a létrejött eseményre. Valamint van egyeseménygenerátor, amely létrehozza magát az eseményt, valamint err ől értesíti azáltala ismert eseményfigyelőket. Ahhoz, hogy meglegyen a kapcsolat az eseménygenerátora, illetve az eseményfigyelő között, a figyelőnek (egy erre alkalmasmetódus segítségével) be kell magát regisztráltatnia a generátor értesítendő figyelőiközé. (Természetesen módot kell adni az így beregisztrált figyelők törlésére is.) Azeseménykezelőket általában egy interfész testesíti meg, amelyet bármilyen objektummegvalósíthat.
10.2. Az eseményvezérelt tervezési modell mevalósítása
Az elméleti leírás könnyebb megértése érdekében megnézünk egy példát atárgyalt modell megvalósítására. Ehhez a 3. fejezet Ember osztályát fogjuk bővítenioly módon, hogy a beszel() metódusa értesítse az őt halló többi ember objektumot atörténésr ől. Az értesített Emberek, ha az üzenet kérdő jelre végződik, igennelválaszolnak az üzenet küldő jének.
Ebben a konkrét esetben az esemény egy BeszedEvent (Példa 10.1) típusúobjektum lesz, amely tartalmazza az üzenet forrását és szövegét. Az eseményforrás akibővített Ember (Példa 10.3) osztály lesz, amely a beszel() metódusának hatásáralétrehoz egy BeszedEvent objektumot, s err ől értesíti a regisztrált eseménykezelőket.Létrehozunk egy BeszedListener interfészt is (Példa 10.2), amelyet az Emberosztály, illetve egy Magno osztály valósít meg. Az ember egy ilyen eseményhatására megvizsgálja, hogy az üzenet kérdés-e, s ha igen, akkor egy igennel válaszolrá. A Magno (bekapcsolt állapotban) minden üzenetet rögzít, s kérésre aztvisszajátszza. A metódusok elnevezése a íratlan szabályok szerint történik. Ezeket
természetesen nem kötelező betartani, de növelik a kód olvashatóságát.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 67/80
Példa 10.1 Eseményosztály létrehozásapubl i c cl ass BeszedEvent {
pr i vat e Ember sour ce;pr i vat e St r i ng message;
publ i c BeszedEvent ( Ember sour ce, St r i ng message){t hi s. sour ce = sour ce;t hi s. message = message;
}publ i c Ember getSour ce( ) {
r et ur n sour ce;}publ i c St r i ng get Message( ) {
r etur n message;}
}
Az eseménykezelő interfész egyetlen metódust ír elő, amely paraméterkéntkapja az esemény objektumot (Példa 10.2). Megállapodás alapján az ehhez hasonlóinterfészeket lehetőleg Listener utótaggal lássuk el.
Példa 10.2 Eseménykezelő interfészpubl i c i nt er f ace BeszedLi st ener {
publ i c voi d val aszol ( BeszedEvent be) ;}
Az Ember osztály több jelentős kibővítést kapott. Tartalmaz egy Vector típusúadattagot, amely a beregisztrált eseményfigyelőket fogja tárolni. Ennek tartalmát azaddBeszedListener(BeszedListener), ill. a removeBeszedListener(BeszedListener)metódusok módosíthatják, ezért ha egy figyelő ki-, vagy be szeretné regisztráltatnimagát az adott eseménygenerátorhoz, ezeket a metódusokat kell használnia. Aharmadik jelentősebb metódus a notifyListeners(BeszedEvent), amely a paraméterformájában kapott esemény objektumot eljuttatja a figyelőkhöz. A beszel() metódusezt az utat használja az értesítésre. (A beszel() metódus egy véletlen szám értékétőlfüggő üzenetet küld a figyelőknek.) A BeszedListener implemetálása miatt meg kellvalósítani a valaszol(BeszedEvent) metódust is, amely eldönti, hogy a kimondottüzenet kérdő jelre végződik-e, s ha igen, akkor egy pozitív választ ír a képernyőre.Ellenkező esetben tudatja a felhasználóval, hogy nem egy kérdést kapott.
Példa 10.3 A kibő vített Ember osztályi mpor t j ava. ut i l . Vector ;
publ i c cl ass Ember i mpl ement s BeszedLi st ener{pr i vat e Vector l i st ener s;. . .publ i c voi d addBeszedLi st ener ( BeszedLi st ener bl ) {
l i st ener s. addEl ement ( bl ) ;}publ i c voi d r emoveBeszedLi st ener ( BeszedLi st ener bl ) {
l i st ener s. r emoveEl ement ( bl ) ;}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 68/80
publ i c voi d beszel ( ) {St r i ng s = Mat h. r andom( ) >0. 5 ? „Val aszol sz?” : „Hel l o”;BeszedEvent be = new BeszedEvent ( t hi s, s) ;not i f yLi stener s(be) ;
}
pr i vat e voi d not i f yLi st ener s( BeszedEvent be) {f or ( i nt i =0; i <l i stener s. si ze( ) ; i ++) {( ( BeszedLi st ener ) l i st ener s. el ement At ( i ) ) . val aszol ( be) ;
}}publ i c voi d val aszol ( BeszedEvent be) {
St r i ng msg = be. getMessage( ) ;i f ( msg. endsWi t h( „?”) ) {
Syst em. out . pr i nt l n( „I gen”) ;} el se {
Syst em. out . pr i nt l n( „Ez nem kér dés! ”) ;
}}. . .
}
A Magno osztály egy új típus, amely szintén megvalósítja a BeszedListenerinterfészt. A valaszol(BeszedEvent) metódusában megvizsgálja, hogy el lett e márindítva, s ha igen, akkor „rögzíti” az üzenetet a szalagjára. (Ebben az esetben egysorvége jelet is „rögzítünk”, hogy „lejátszáskor” izlésesebben jelenjen meg a szöveg)
Példa 10.4 Eseménykezelő interfész megvalósítása
publ i c cl ass Magno i mpl ement s BeszedLi st ener{pr i vat e st at i c f i nal St r i ng sor Vege = „\ n”;pr i vat e St r i ngBuf f er szal ag;pr i vat e bool ean f el vesz;
publ i c voi d val aszol ( BeszedEvent be) {i f ( f el vesz) {
szal ag. append( be. get Message( ) ) ;szal ag. append( sorVege) ;
}}
publ i c voi d l ej at szas( ) {Syst em. out . pr i nt l n( szal ag) ;}publ i c voi d t or ol ( ) {
szal ag. del et e( 0, szal ag. l engt h( ) - 1) ;}publ i c voi d st op( ) {
f el vesz = f al se;}publ i c voi d star t ( ) {
f el vesz = t r ue;
}}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 69/80
Az eseményvezérelt fejlesztési modellt követő osztályaink teszteléséhez egyDemo alkalmazást hozunk létre (Példa 10.5) Az alkalmazás létrehoz három Ember ésegy Magno típusú objektumot, majd elindítja a Magnot. Ezután következik afigyelők regisztrálása, majd néhány esemény generálása. A végén a Magno általrögzített szövegeket „lejátszuk”. A program kimenetének elemzését az olvasóra
bizzuk.
Példa 10.5 Példaalkalmazás eseménykezelő osztályaink használatárapubl i c cl ass Demo{
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {Ember e1 = new Ember( „El so”) ;Ember e2 = new Ember ( „Masodi k”) ;Ember e3 = new Ember ( „Har madi k”) ;Magno m = new Magno( ) ;m. start ( ) ;e1. addBeszedLi st ener ( m) ;e2. addBeszedLi st ener ( m) ;e3. addBeszedLi st ener ( m) ;e1. addBeszedLi st ener ( e2) ;e1. addBeszedLi st ener ( e3) ;e2. addBeszedLi st ener ( e3) ;Syst em. out . pr i nt l n( „Az el ső ember beszél ”) ;e1. beszel ( ) ;Syst em. out . pr i nt l n( „Az másodi k ember beszél ”) ;e2. beszel ( ) ;Syst em. out . pr i nt l n( „Az har madi k ember beszél ”) ;
e3. beszel ( ) ;m. st op( ) ;m. l ej at szas( ) ;
}}
11. Grafikus felületek létrehozása (Swing)
A Java-ban két jelentősebb megoldás kínálkozik GUI30 fejlesztésére. Az egyikaz AWT31, a másik pedig a Swing32. A kezdeteknél az AWT volt az egyeduralkodó,amely az operációs rendszer komponenseit használva rajzolta ki a megfelelő
felületelemeket, s ennek köszönhetően jelentősen megkötötte a fejlesztők kezét. ASwing az 1.2-es Java-ban jelent meg először, s az AWT-vel szemben komponenseimár önmagukat rajzolták a képernyőre, nagyobb flexibilitást adva ezzel a felületekkialakítóinak. Ennek azonban megvolt a hátránya, amelyet az er őforrás-felhasználásterületén kell keresnünk. A Swing elemek kirajzolása jóval idő-, és memória-igényesebb, de az egyre jobban gyorsuló számítógépeknek köszönhetően ez már nemannyira okoz problémát.
30
GUI - Graphical User Interface (Grafikus Felhasználói Felület)31 AWT- Abstract Window Toolkit (Absztrakt Ablakozó Keretrendszer)32 Swing - fantázianév
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 70/80
Csak a Swing csomag több száz osztályt tartalmaz, amelyek mindegyikéreterjedelmi korlátok miatt nem térhetünk ki, ezért inkább egy átfogó képet szeretnénkadni a lehetőségekr ől, amellyel (valamint a már sokat emlegetett dokumentációval)felvértezve már bárki könnyen boldogulhat a grafikus felületek világában.
11.1. Alapvető GUI elemek, pakolási stratégiákA Swing osztályait a javax.swing csomagban, illetve annak alcsomagjaiban
találjuk, de a mögöttes filozófiai hasonlóság miatt több osztályt kell használnunk azAWT-s örökségből is (java.awt csomag, illetve az események kezeléséhez a
java.awt.event csomag).
A Java ablakozó technikája alapvetően komponens alapú, tehát a különböző grafikai felületeket kisebb alkotóelemekből kell összeraknunk. A komponenseket kétnagy csoportra oszthatjuk, az egyik a konténerek csoportja, míg a másik az egyszer ű
komponensek csoportja. A konténerek abban különböznek az egyszer ű komponensektől, hogy rájuk (meghatározott stratégia szerint) újabb konténerek,illetve komponensek helyezhetőek el. Az itt említett „meghatározott stratégiát”nevezzük pakolási stratégiának, amely megmondja, hogy az adott konténerre rakottkomponenst hogyan kell a már eddig felrakottakhoz igazítani.
A legalapvető bb konténer a JPanel, amelynek nincs vizuális eleme, tehát azablakra helyezéskor nem látszik. Csak arra szolgál, hogy olyan ablakrészekre, ahovaa pakolási stratégia csak egy komponens elhelyezését engedélyezi, több komponenstis fel lehessen rakni. (Egyszer űen felhelyezünk egy JPanel-t, s rárakjuk a kívánt
elemeket). A másik fontos konténer a JFrame, amely egy keretes, fejléces,funkciógombos ablakot testesít meg. A JFrame konténer látható és módosíthatófelületét a getContentPane() metódussal kérhetjük el. Erre a konténerre pakolhatjukaz ablakon megjeleníteni kívánt elemeket. Egy komponens konténeren valóelhelyezését a konténer add() metódusával érhetjük el.
A pakolási stratégiák közül érdemes megjegyezni a BorderLayout-ot, amely azadott konténert öt részre osztja (Ábra 11-1). Ha egy komponenst fel szeretnénkhelyezni egy BorderLayout pakolási stratégiával rendelkező konténerre, akkor azadd() metódusban a feltenni kívánt komponens mögött meg kell adni azt is, hogy az
adott elem hova kerüljön. Ennek kijelölésére megfelelő konstansok szolgálnak(BorderLayout.NORTH, BorderLayout.WEST, stb.). Egy másik jelentős pakolásistratégia a FlowLayout, amely a ráhelyezett elemeket sorban egymás mellé helyezi, saz így kapott komponens-együttest a megadott helyre igazítja (FlowLayout.LEFT, akonténer bal oldalára, stb.). Fontos még a GridLayout, valamint a GridBagLayout,amelyek a konstruktoruk paramétereként megadott egész számok alapján sorokra ésoszlopokra osztják a felületet. A GridLayout egy elemnek egy cellát engedélyez, míga GridBagLayout használata esetén egy komponens több cellát is elfoglalhat.Többször alkalmazható stratégia a BoxLayout, amely a FlowLayout-hoz hasonló,azzal a különbséggel, hogy nem csak vízszintes, hanem függőleges elrendezést is
lehetővé tesz. (BoxLayout használata esetén kényelmesebb a JPanel helyett a Boxkonténer alkalmazása.)
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 71/80
Ábra 11-1 A BorderLayout elrendezése
A fontosabb komponensek:
JButton - gomb JLabel - szöveg megjelenítésére alkalmas címke JTextField - egysoros szövegbeviteli mező JTextArea - többsoros szövegbeviteli mező JCheckBox - jelölőnégyzet JComboBox - legördülő menü
Ezen elemek használatához lásd a dokumentációt, illetve a fejezet példáit.
11.2. A Swing eseménykezelése
A Swing vezérlőelemeinek (gomb, legördülő lista, stb.) használata eseményke-zelőkön keresztül valósul meg, de ugyanúgy eseménykezelés szükséges az egérhasználatához is. Az eseményosztályokat, illetve a hozzájuk tartozó eseményfigyelő-ket a java.awt.event csomag tartalmazza, amelyek közül a legfontosabban azActionListener, a MouseListener, valamint a WindowListener. Például egy gomblenyomásakor egy ActionEvent esemény generálódik, amely eljut a regisztráltfigyelőkhöz, amelyek már végre tudják hajtani a szükséges utasításokat. Erreláthatunk egy demonstrációt a Példa 11.1-n. Az eseményfigyelő által meghatározottmetódus az actionPerformed(ActionEvent), amely az ActionEvent típusú objektumgetActionCommand() metódusával tudhatja meg, hogy mi a megnyomott gomb
felirata. (Ez az alapértelmezés, de természetesen az „action command” állítható.) AJFrame setDefaultCloseOperation(int) állíthatjuk, hogy az ablak mit csináljon, ha afelhasználó a bezáró funkciógombot megnyomja. Ugyanezen osztály String-et várókonstruktora (amelyet a super segítségével hívtunk meg) egy ablakot hoz létre, s a
paraméterként átadott szöveget írja a fejlécbe. A main() metódusban használt pack()metódus az optimális méret kiszámítását végzi. Ha ez számunkra nem megfelelő,akkor használjuk a setSize(int, int) metódust az ablak méretének beállításához. Azablak alapértelmezés szerint a képernyő bal felső sarkában jelenik meg. Ezt asetLocation(int, int) metódussal módosíthatjuk. A setVisible(boolean) padig azablakot láthatóvá teszi, illetve false érték esetén eltünteti.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 72/80
Példa 11.1 Gombok használatai mpor t j ava. awt . event . *;i mpor t j ava. awt . *;i mpor t j avax. swi ng. *;
publ i c cl ass Gombos ext ends J Fr ame i mpl ement s Act i onLi st ener{pr i vat e J Text Fi el d f i el d;
publ i c Gombos( ) {super ( "Abl ak gombbal " ) ;set Def aul t Cl oseOperat i on( J Frame. EXI T_ON_CLOSE) ; J Panel cp = ( J Panel ) getContentPane( ) ;cp. setLayout ( new Bor der Layout ( ) ) ;f i el d = new J Text Fi el d( "" , 20) ;cp. add( f i el d, Bor der Layout . CENTER) ; J But t on exi t But t on = new J But t on( "Ki l ép") ;
exi t But t on. addActi onLi st ener ( t hi s) ; J But t on execBut t on = new J But t on( "Dupl áz" ) ;execBut t on. addAct i onLi st ener ( t hi s) ; J But t on del But t on = new J But t on( "Töröl " ) ;del But t on. addAct i onLi st ener ( t hi s) ; J Panel but t onPanel = new J Panel ( new Fl owLayout ( ) ) ;but t onPanel . add( execBut t on) ;but t onPanel . add( exi t But t on) ;but t onPanel . add( del But t on) ;cp. add( but t onPanel , Border Layout . SOUTH) ;
}
publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {Gombos g = new Gombos( ) ;g. pack( ) ;g. set Vi s i bl e( t r ue) ;
}
publ i c voi d act i onPer f or med( Act i onEvent ae) {i f ( ae. get Act i onCommand( ) . equal s( "Ki l ép") ) {
Syst em. exi t ( 0) ;} el se i f ( ae. get Act i onCommand( ) . equal s( "Dupl áz" ) ) {
f i el d. set Text ( f i el d. get Text ( ) + f i el d. get Text ( ) ) ;} el se i f ( ae. get Act i onCommand( ) . equal s( "Tör öl " ) ) {
f i el d. setText ( " " ) ;}
}}
Megj.: A JTextField osztály getText() metódusával a szövegmező ben találhatószöveget tudhatjuk meg, míg a setText(String) metódussal ezt a szövegetváltoztathatjuk. (A szövegmező szerkeszthetőségét a setEditable(boolean) metódusszabályozza.)
A létrehozott ablakot az Ábra 11-2 szemlélteti.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 73/80
Ábra 11-2 Az elkészült ablak
11.3. Az MVC modell a Swingben
A Model-View-Conroller tervezési mintát más sok szakkönyvben sikeresen bemutatták, ezért ennek a fejezetnek nem célja a részletes leírás. Azt szeretnénkmegmutatni, hogy hogyan integrálták ezt a modellt a Java Swing elemeibe. Azelőzetes tervek szerint minden vizuális komponens ezen minta alapján készült volna,
s ezt többé-kevésbé sikerült is megvalósítani. A mi példánk a JTable osztálymodelljét mutatja be működés közben. Ennek a komponensnek a segítségévelgyorsan készíthetünk különböző táblázatokat, amelyet mi egy olyan szorzótáblakészítésére használunk, amely sorainak száma egy legördülő menü segítségévelváltoztatható.
A modell osztály a Példa 11.2-n látható. A megvalósítandó metódusok közül alényegesebbek:
getRowCount() - A tábla sorainak számát határozza meg getColumnCount() - A tábla oszlopainak számát határozza meg
getValueAt(int,int) - A paraméterek által azonosított cella értékét határozzameg. getColumnClass(int) - A paraméter által azonosított oszlopban lévő értékek
típusát adja meg. A típustól függően változik a megjelenítés. Példáullogikai érték esetén egy jelölőnégyzet jelenik meg az oszlop celláiban,szám típus esetén az értékek jobbra, szöveg esetén balra lesznekigazítva. (Természetesen a cellákban lévő értékeket megjelenítő ésszerkesztő komponensek is változtathatók, ha nem vagyunkmegelégedve az alapbeállításokkal.)
Példa 11.2 Egy tábla (JTable) modelljei mpor t j avax. swi ng. t abl e. Tabl eModel ;i mpor t j avax. swi ng. event . Tabl eModel Li st ener ;
publ i c cl ass Szor zoTabl aModel i mpl ement s Tabl eModel {pr i vat e I nt eger t emp = new I nt eger ( 0) ;pr i vat e i nt sor ok, oszl opok;
publ i c Szor zoTabl aModel ( i nt sor , i nt oszl op) {sorok = sor ;oszl opok = oszl op;
}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 74/80
publ i c voi d set Sor ok( i nt sor ok){t hi s. sor ok = sor ok;
}publ i c voi d set Oszl opok( i nt oszl opok) {
t hi s. oszl opok = oszl opok;
}
publ i c i nt get RowCount ( ) {r et ur n sor ok;
}publ i c i nt get Col umnCount ( ) {
r et ur n oszl opok;}publ i c St r i ng get Col umnName( i nt oszl op) {
r et ur n I nt eger . t oSt r i ng( oszl op+1) ;}
publ i c Cl ass get Col umnCl ass( i nt oszl op) {try{r et ur n Cl ass. f or Name( "j ava. l ang. I nt eger ") ;
}catch( Cl assNot FoundExcept i on cnf e) {r et ur n t emp. get Cl ass( ) ;
}}publ i c bool ean i sCel l Edi t abl e( i nt sor , i nt oszl op) {
r et ur n f al se;}publ i c Obj ect get Val ueAt ( i nt sor , i nt oszl op) {
r et ur n new I nt eger ( ( oszl op+1) * ( sor +1) ) ;}
publ i c voi d set Val ueAt ( Obj ect er t ek, i nt sor , i nt oszl op) {/ / Nem használ j uk
}publ i c voi d addTabl eModel Li st ener ( Tabl eModel Li st ener t ml ) {
/ / Nem használ j uk}publ i c voi d r emoveTabl eModel Li st ener (
Tabl eModel Li st ener t ml ) {
/ / Nem használ j uk}
}
Az elkészített modellt egy JTable típusú objektum konstruktorának átadva márrajzolódik is a kívánt értékeket tartalmazó táblázat. Ezek után már csak a modelltkell változtatnunk, s a változtatások automatikusan megjelennek a kirajzolt elemenis. Erre mutat egy megoldást a Példa 11.3, ahol a sorok száma egy legördülő menüvel adható meg. Amint a menü értéke változik, a hozzá regisztrálteseményfigyelő a változásnak megfelelően változtatja a modellt, s ezáltal atáblázatot.
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 75/80
Példa 11.3 A modell alkalmazásai mpor t j ava. awt . event . *;i mpor t j ava. awt . *;i mpor t j avax. swi ng. *;i mpor t j ava. ut i l . Vector ;
publ i c cl ass Szor zoTabl a extends J Framei mpl ement s Act i onLi st ener , I t emLi st ener {
pr i vat e J ComboBox sorBox;pr i vat e Szor zoTabl aModel model ;pr i vat e J Tabl e t abl a;
publ i c Szor zoTabl a( ) {super ( "Szor zó Tábl a" ) ;set Def aul t Cl oseOperat i on( J Frame. EXI T_ON_CLOSE) ; J Panel cp = ( J Panel ) getContentPane( ) ;
cp. setLayout ( new Bor der Layout ( ) ) ; J Panel i nput Panel = new J Panel ( new Fl owLayout ( ) ) ;i nput Panel . add( new J Label ( "Sor ok száma") ) ;Vector val ues = new Vector ( ) ;f or ( i nt i =5; i <26; i ++)
val ues. addEl ement ( new I nt eger ( i ) ) ;sor Box = new J ComboBox( val ues) ;sor Box. set Sel ect edI t em( new I nt eger ( 10) ) ;sor Box. addI t emLi st ener ( t hi s) ;i nput Panel . add( sor Box) ;cp. add( i nput Panel , Bor derLayout . NORTH) ;
model = new SzorzoTabl aModel ( 10, 10) ;t abl a = new J Tabl e(model ) ;cp. add( t abl a, Bor der Layout . CENTER) ; J But t on exi t But t on = new J But t on( "Ki l ép") ;exi t But t on. addActi onLi st ener ( t hi s) ; J Panel but t onPanel = new J Panel ( new Fl owLayout ( ) ) ;but t onPanel . add( exi t But t on) ;cp. add( but t onPanel , Border Layout . SOUTH) ;
}publ i c st at i c voi d mai n( St r i ng[ ] ar gs) {
Gomb g = new Gomb( ) ;
g. pack( ) ;g. set Vi s i bl e( t r ue) ;
}publ i c voi d act i onPer f or med( Act i onEvent ae) {
Syst em. exi t ( 0) ; / / Ki l épés}publ i c voi d i t emSt ateChanged( I t emEvent i e){
i f ( i e. get St at eChange( ) == i e. SELECTED) {model . set Sor ok( ( ( I nt eger ) i e. get I t em( ) ) . i nt Val ue( ) ) ;pack( ) ;
}
}}
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 76/80
Hiba! A stílus nem létezik. fejezet: Hiba! A stílus nem léte
Ábra 11-3 Az elkészült program egy futási képe
- 75 -
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 77/80
Példajegyzék
PÉLDA 1.1 A HELLO VILAG PROGRAMUNK FORRÁSA ..................................................................4PÉLDA 1.2 A LEGRÖVIDEBB ÖNÁLLÓ, FORDÍTHATÓ EGYSÉG ....................................................... 5PÉLDA 1.3 A LEGRÖVIDEBB FUTTATHATÓ JAVA PROGRAM ......................................................... 5PÉLDA 2.1 SZEKVENCIÁK .......................................................................................................... 12PÉLDA 2.2 FELTÉTELES KIFEJEZÉS............................................................................................. 12PÉLDA 2.3 FELTÉTELES ELÁGAZÁS............................................................................................ 13PÉLDA 2.4 ÖSSZETETT ELÁGAZÁS ............................................................................................. 13PÉLDA 2.5 ITERÁCIÓK KÖZÖTTI ÁTJÁRÁS .................................................................................. 15PÉLDA 2.6 TERMÉSZETES SZÁMOK KIÍRÁSA A KÉPERNYŐRE KÜLÖNBÖZŐ ITERÁCIÓK
HASZNÁLATÁVAL ..............................................................................................................15PÉLDA 2.7 BREAK UTASÍTÁS HASZNÁLATA SWITCH SZERKEZETBEN ..........................................16PÉLDA 2.8 A BREAK ÉS CONTINUE KÖZÖTTI KÜLÖNBSÉG .......................................................... 16PÉLDA 2.9 CIMKE HASZNÁLATA................................................................................................ 17PÉLDA 3.1 ADATTAGOK LÉTREHOZÁSA.....................................................................................18PÉLDA 3.2 ADATTAGOK ELLÁTÁSA KEZDŐÉRTÉKKEL ...............................................................18PÉLDA 3.3 ADATTAGOK ÉS METÓDUSOK ................................................................................... 19PÉLDA 3.4 K ONSTRUKTOROK LÉTREHOZÁSA ............................................................................ 20PÉLDA 3.5 OBJEKTUMOK PÉLDÁNYOSÍTÁSA.............................................................................. 20PÉLDA 3.6 LESZÁRMAZTATÁS................................................................................................... 21PÉLDA 3.7 ADATELREJTÉS LÁTHATÓSÁGI SZINTEK HASZNÁLATÁVAL....................................... 22
PÉLDA 3.8 I NTERFÉSZ IMPLEMENTÁLÁSA.................................................................................. 24PÉLDA 3.9 OSZTÁLY SZINTŰ ADATTAG ÉS METÓDUS HASZNÁLATA ...........................................24PÉLDA 3.10 OBJEKTUM SZINTŰ KONSTANS ............................................................................... 25PÉLDA 3.11 OSZTÁLY SZINTŰ KONSTANS LÉTREHOZÁSA .......................................................... 25PÉLDA 3.12 STATIKUS INICIALIZÁTOR .......................................................................................25PÉLDA 3.13 ALLAT.JAVA...........................................................................................................26PÉLDA 3.14 R EPULO.JAVA......................................................................................................... 27PÉLDA 3.15 MADAR .JAVA ......................................................................................................... 27PÉLDA 3.16 FECSKE.JAVA ......................................................................................................... 28PÉLDA 3.17 STRUCC.JAVA......................................................................................................... 28PÉLDA 3.18 EMLOS.JAVA .......................................................................................................... 28
PÉLDA 3.19 TIGRIS.JAVA ...........................................................................................................29PÉLDA 3.20 EMBER .JAVA .......................................................................................................... 29PÉLDA 3.21 SUPERMAN.JAVA .................................................................................................... 30PÉLDA 4.1 CSOMAGDEFINÍCIÓ AZ ALLAT.JAVA FILE-BAN ......................................................... 32PÉLDA 4.2 ALCSOMAG HASZNÁLATA ÉS TELJES CSOMAG IMPORTÁLÁSA A MADAR .JAVA-BAN .32PÉLDA 4.3 EGY ADOTT OSZTÁLY IMPORTÁLÁSA MÁS CSOMAGBÓL ...........................................32PÉLDA 4.4 AZ EMBER OSZTÁLY DOKUMENTÁCIÓS MEGJEGYZÉSEKKEL .................................... 33PÉLDA 5.1 TÖMB HASZNÁLATA ................................................................................................. 35PÉLDA 5.2 A COMPARABLE INTERFÉSZ HASZNÁLATA ...............................................................39PÉLDA 5.3 OBJEKTUMOK RENDEZÉSE........................................................................................40PÉLDA 5.4 AZ AKTUÁLIS DÁTUM KIÍRÁSA A KÉPERNYŐRE ........................................................ 40PÉLDA 6.1 BEÉPÍTETT KIVÉTELEK ............................................................................................. 43PÉLDA 6.2 EGY EGYSZER Ű KIVÉTELOSZTÁLY FORRÁSKÓDJA .................................................... 45
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 78/80
PÉLDA 6.3 EGY ÖSSZETETTEBB KIVÉTEL OSZTÁLY.................................................................... 45PÉLDA 6.4 SAJÁT KIVÉTELEK HASZNÁLATA .............................................................................. 45PÉLDA 6.5 SAJÁT KIVÉTELEK ELKAPÁSA ................................................................................... 46PÉLDA 7.1 A BILLENTYŰZET ÉS A CSATORNÁK HASZNÁLATA.................................................... 47PÉLDA 7.2 EGY FILE ADATAINAK KÉPERNYŐRE LISTÁZÁSA....................................................... 49
PÉLDA 7.3 FILE MÁSOLÁSA MEGADOTT HELYRE ÉS NÉVVEL ..................................................... 50PÉLDA 7.4 SZERIALIZÁLHATÓ OSZTÁLY DEFINÍCIÓJA................................................................51PÉLDA 7.5 OBJEKTUM FILE-BA ÍRÁSA, S VISSZAOLVASÁSA (SZERIALIZÁCIÓ) ............................ 51PÉLDA 8.1 SZÁL LÉTREHOZÁSA ÉS INDÍTÁSA............................................................................. 54PÉLDA 8.2 SZÁLAK ÖSSZEKAPCSOLÁSA .................................................................................... 55PÉLDA 8.3 SZÁLAK HASZNÁLATÁNAK LEHETŐSÉGEI.................................................................56PÉLDA 8.4 METÓDUS SZINKRONIZÁSLÁSA ................................................................................ 58PÉLDA 9.1 EGY KLIENS KISZOLGÁLÁSÁRA ALKALMAS SZERVER ............................................... 60PÉLDA 9.2 EGY KLIENS ALKALMAZÁS A FORDÍTÓ SZERVERHEZ ................................................ 61PÉLDA 9.3 TÖBB KLIENS SOROS KISZOLGÁLÁSA........................................................................ 62PÉLDA 9.4 SZERVER , KLIENS ÁLTAL VEZÉRELT LEÁLLÁSSAL .................................................... 63
PÉLDA 9.5 TÖBB KLIENS PÁRHUZAMOS KISZOLGÁLÁSÁRA ALKALMAS SZERVER ...................... 63PÉLDA 10.1 ESEMÉNYOSZTÁLY LÉTREHOZÁSA ......................................................................... 66PÉLDA 10.2 ESEMÉNYKEZELŐ INTERFÉSZ ................................................................................. 66PÉLDA 10.3 A KIBŐVÍTETT EMBER OSZTÁLY............................................................................. 66PÉLDA 10.4 ESEMÉNYKEZELŐ INTERFÉSZ MEGVALÓSÍTÁSA...................................................... 67PÉLDA 10.5 PÉLDAALKALMAZÁS ESEMÉNYKEZELŐ OSZTÁLYAINK HASZNÁLATÁRA................. 68PÉLDA 11.1 GOMBOK HASZNÁLATA .......................................................................................... 71PÉLDA 11.2 EGY TÁBLA (JTABLE) MODELLJE ........................................................................... 72PÉLDA 11.3 A MODELL ALKALMAZÁSA .....................................................................................74
Ábrajegyzék
ÁBRA 1-1 PLATFORMOK RÉTEGZŐDÉSE ...................................................................................... 2ÁBRA 1-2 EGY JAVA PROGRAM ÁLLAPOTÁTMENETEI..................................................................5
ÁBRA 1-3 OBJEKTUM = ADAT + KÓD EGYSÉGE............................................................................ 7ÁBRA 1-4 I NTERFÉSZEK ÉRTELMEZÉSE .......................................................................................8ÁBRA 1-5 ÖRÖKLŐDÉS................................................................................................................8ÁBRA 3-1 OSZTÁLYDIAGRAM EGY ÖSSZETETT PÉLDÁHOZ ........................................................ 26ÁBRA 8-1 SZEKVENCIÁLIS VÉGREHAJTÁSÚ UTASÍTÁSOK PROCESSZORHASZNÁLATA ................ 52ÁBRA 8-2 PÁRHUZAMOS VÉGREHAJTÁSÚ UTASÍTÁSOK PROCESSZORHASZNÁLATA ...................53ÁBRA 8-3 SZÁLAK ÁLLAPOTÁTMENETEI ................................................................................... 53ÁBRA 11-1 A BORDER LAYOUT ELRENDEZÉSE .......................................................................... 70ÁBRA 11-2 AZ ELKÉSZÜLT ABLAK ............................................................................................ 72ÁBRA 11-3 AZ ELKÉSZÜLT PROGRAM EGY FUTÁSI KÉPE............................................................ 75
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 79/80
Tartalomjegyzék
1. ............................................................................................................................ 1Bevezetés1.1. ................................................................................................ 1A Java nyelv története1.2. .................................................................................... 2A Java platformfüggetlensége1.3. ............................................................................... 2A Java alkalmazásai, lehetőségei1.4. ................................................................................................... 3Eszközök és verziók 1.5. ........................................................................... 4A Hello Vilag program Java-módra1.6. ........................................................................................................... 6Az OOP alapjai
1.6.1. .................................................................................................... 6Egységbezárás1.6.2. .................................................................. 7Adatelrejtés, üzenetküldés, interfész
1.6.3. ...............................................................................................................8Öröklés1.6.4. .................................................................................................... 9Polimorfizmus2. ......................................................................................................... 9Vezérlési szerkezetek
2.1. .............................................................................................................9Alapfogalmak 2.2. ................................................................................................................ 11Szekvencia2.3. ................................................................................................ 12Feltételes elágazások 2.4. .................................................................................................................... 14Iterációk 2.5. .................................................................................. 16Feltétel nélküli vezérlésátadás
3. ................................................................................................................ 17OOP a Java-ban3.1. .............................................................................................. 18Adattagok, metódusok 3.2. .......................................................................... 20Konstruktor, objektum létrehozása
3.3. ......................................................................................21Öröklés, láthatósági szintek 3.4. ............................................................ 23A tervezés és a megvalósítás szétválasztása3.5. ............................... 24Osztály szintű adatok, metódusok, konstansok, inicializátorok 3.6. ............................................................................................. 26Egy összetettebb példa
4. ................................................................................................................ 31„Rendteremtés”4.1. ................................................................................................................. 31Csomagok 4.2. .................................................................... 33Megjegyzések, dokumentáció-készítés
5. ...........................................................................................................35Alapvető osztályok 5.1. ...................................................................................................... 35Tömbök kezelése5.2. .................................................................................................. 36A java.lang csomag5.3. .................................................................................................... 39A java.util csomag
6. .................................................................................................................. 41Kivételkezelés6.1. ............................................................................................. 41A Java kivételkezelése6.2. ................................................................................................ 43„Beépített” kivételek 6.3. .............................................. 44„Saját” kivételek létrehozása, kiváltása és lekezelése
7. ......................................................................................................... 46I/O kezelés Java-ban7.1. ............................................................. 46A csatorna (stream) fogalma, osztályozásai7.2. ............................................................................................ 47Alapfunkciók és szűr ők 7.3. ......................................................................................48Kapcsolat a file-rendszerrel7.4. .............................................................................................................50Szerializáció
8. ................................................................................................. 52Párhuzamos programozás8.1. ......................................................... 52A párhuzamos programozás elmélete, előnyei8.2. .....................................................................................53Szálak állapotai, életciklusa8.3. ................................................................. 54Szálak kezelése, szinkronizálás Java-ban
rrás: http://www.doksi.hu
7/25/2019 Java Nyelv Programozoknak
http://slidepdf.com/reader/full/java-nyelv-programozoknak 80/80
9. ......................................................................................59Hálózati alkalmazások készítése9.1. .................................. 59Összeköttetés alapú, és összeköttetésmentes hálózati modell9.2. ................................................................................ 60A java.net csomag alkalmazása
9.2.1. ........................................................... 60Összeköttetés alapú szerver alkalmazás9.2.2. ........................................................................ 61Kliens alkalmazás a szerverhez
9.2.3. .............................................................................. 62A szerver továbbfejlesztése9.2.4. ............................................................ 64A java.net csomag további lehetőségei10. ............................................................................. 65Eseményvezérelt fejlesztési modell
10.1. ...................................................................................................... 65Elméleti háttér 10.2. ............................................. 65Az eseményvezérelt tervezési modell mevalósítása
11. ........................................................................ 68Grafikus felületek létrehozása (Swing)11.1. ........................................................... 69Alapvető GUI elemek, pakolási stratégiák 11.2. ................................................................................... 70A Swing eseménykezelése11.3. ............................................................................... 72Az MVC modell a Swingben
rrás: http://www.doksi.hu