Java programozási nyelv 9. rész – Kivételkezelés Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2005. szeptember
A Java programozási nyelv
Soós Sándor
1/24
Tartalomjegyzék ● ● ● ● ● ● ● ● ● ●
Mit nevezünk kivételkezelésnek? Kivétel keletkezése Kivétel kiváltásának típusai A megfelelő kivételkezelő keresése A kivétel elkapása (catching exception) A kivétel kiváltása Java-ban A kivétel elkapása Java-ban A finally blokk Kivételek specifikálása Klasszikus példa a Java nyelv specifikációjából
A Java programozási nyelv
Soós Sándor
2/24
Mit nevezünk kivételkezelésnek? ●
Szűkebb értelemben: –
●
Tágabb értelemben: – –
●
A programban fellépő futásidejű hibák kezelését. A program normál logikájához képest különleges, attól eltérő helyzetek kezelését. Ez azt is jelenti, hogy abszolút nem hibás esetek kezelését is megoldhatjuk a kivételkezelés mechanizmusával.
A végső cél: –
Teljes egészében kezünkben tartsuk a program működését, minden helyzetben a szándékaink szerint reagáljon a program. Soha ne forduljon elő olyan eset, amikor a program úgy fejeződik be, hogy valamit "elvarratlanul" hagyott.
A Java programozási nyelv
Soós Sándor
3/24
Miért fontos ez? ●
Milyen problémákat okozhat egy rendkívüli program leállás? –
adatvesztés: ● ●
–
időveszteség: ●
–
nyitva maradt fájlok még el nem mentett, berögzített adat. A felhasználó begépelt 5 oldalnyi szöveget, amikor a program "elszáll", vagy hibajelzéssel leáll. egy 5 órája futó kalkuláció a végeredmény elkészülte és a részeredmények elmentése nélkül hibajelzéssel leáll.
erőforrások fogvatartása ●
a program futása során lefoglal bizonyos erőforrásokat (fájlok, adatbázis rekordok), ezeket a futás végén szabadítaná fel. –
A Java programozási nyelv
pl. kórházi rendszer, lefagy a terminál, zárolt marad a rekord Soós Sándor
4/24
Mi a megoldás? ● ●
A programot fel kell készíteni minden eshetőségre. Például: Az előző program hibakezeléssel:
Egy egyszerű program: program { fuggveny1(); fuggveny2(); fuggveny3(); }
Miért nem jó ez? A Java programozási nyelv
program { if (fuggveny1() = OK) { if (fuggveny2() = OK) { if (fuggveny3() = OK) { // minden rendben } else { // hibakezelés3 } } else { // hibakezelés2 } } else { // hibakezelés1 } } Soós Sándor
5/24
Miért nem jó ez a megoldás? ●
A hibakezelés elrejti, széttördeli az eredeti programlogikát: – –
●
●
nehezen olvasható kód nehezen javítható, módosítható a kód
A hibakezelő programrésznek nincs információja a hiba jellegéről, okáról Nagyobb programok esetén ez a megoldás kivitelezhetetlen, sőt... –
hiba bekövetkezhet a hibakezelő programrészben is, ezért oda is kellene ellenőrzés, ...
A Java programozási nyelv
Soós Sándor
6/24
A szép megoldás class Exception1 extends Exception {} class Exception2 extends Exception {} class Exception3 extends Exception {} Pogram() { try { fuggveny1(); fuggveny2(); fuggveny3(); } catch(Exception1 hiba1) { /* hibakezelés1 */ } catch(Exception2 hiba2) { /* hibakezelés2 */ } catch(Exception3 hiba3) { /* hibakezelés3 */ } } A Java programozási nyelv
Soós Sándor
7/24
A kivételkezelés ötlete ●
●
●
●
Válasszuk szét az eredeti programlogikát és a kivételes helyzetek (hibaállapotok) kezelését A kivételkezelő kapjon információt a hiba típusáról, helyéről és egyéb körülményeiről A kivételkezelő legyen képes visszatérni az eredeti programlogikához, ha a hiba jellege ezt lehetővé teszi. Legyen lehetőség garantálni a program és minden részprogram korrekt befejeződését bármilyen körülmények fennállása esetén (fájlok bezárása, erőforrások felszabadítása, stb.)
A Java programozási nyelv
Soós Sándor
8/24
Kivételkezelés a Java-ban ●
●
● ●
Ezeket az elveket különböző módokon valósítják meg a különböző programnyelvek (C++, Ada, Eiffel, Object Pascal – Delphi) A Java ezt is teljes mértékben osztályokkal valósítja meg. A kivételeket is beépíti az osztályhierarchiába. A kivételek csak annyiban kivételesek, hogy ők "kiválthatóak", míg a többi osztály nem.
A Java programozási nyelv
Soós Sándor
9/24
Kivétel keletkezése ●
Amikor valamilyen hiba lép fel egy metódus végrehajtása során (vagy a programozó külön útra kívánja terelni a végrehajtást), akkor – – –
●
●
létrejön egy kivétel objektum A "hiba" adatai és a program állapota rögzítésre kerül a kivétel objektumban Az objektum a Java Virtuális Gép felügyelete alá kerül.
Ezt nevezzük a kivétel kiváltásának (throwing exception) Ekkor a blokk futása megszakad, oda már nem kerül vissza a vezérlés.
A Java programozási nyelv
Soós Sándor
10/24
Kivétel kiváltásának típusai ●
Kivétel háromféleképpen keletkezhet: –
–
–
A program futása közben valamilyen rendellenes dolog történt: nullával osztás, erőforrások elfogyása, osztálybetöltési hiba, stb. A program végrehajtott egy throw utasítást. Ezt megteheti valamely Java könyvtári osztály, vagy maga a programozó Egy aszinkron kivétel lépett fel. Ez akkor következhet be, amikor a program több szálon fut és egy másik szál futása megszakad. Ezzel most nem foglalkozunk.
A Java programozási nyelv
Soós Sándor
11/24
A megfelelő kivételkezelő keresése ●
●
A kivétel kiváltása után a JVM megkeresi a megfelelő kivételkezelő kódblokkot. Egy kivételkezelő kódblokk akkor megfelelő, ha – – –
a hatáskörében keletkezett a kivétel a típusa megfelelő a kiváltott kivételhez. A típus akkor megfelelő, ha ● ●
– ●
vagy a kezelő által kezelt kivétel típusa azonos a kivételével vagy az őse annak
A blokkok egymásba ágyazása miatt több alkalmas kezelő is lehet. Ezek közül a legbelsőt választja a JVM.
Ezt nevezzük a kivétel elkapásának (catching exception)
A Java programozási nyelv
Soós Sándor
12/24
A kivétel elkapása (catching exception) ●
● ●
●
●
A megfelelő kivételkezelő blokk megtalálásakor a JVM átadja a vezérlést a kiválasztott kezelőnek Lefut a blokk A kivételkezelő blokk lefutása után a kezelő blokk utáni utasításra kerül a vezérlés. A kivételkezelés közben is kiváltódhat kivétel, ekkor a blokk végrehajtása megszakad, és ugyanaz lezajlik, mint az előbb. Ha a JVM nem talál alkalmas kivételkezelő blokkot, akkor megszakad a program futása, (legalábbis az egyszálú programok esetében.)
A Java programozási nyelv
Soós Sándor
13/24
Konkrét példa ●
Bevezetésképpen nézzünk meg egy konkrét példát! – –
A Verem.java fájlban látjuk egy verem adattípus részletét A VeremTeszt.java fájlban pedig kipróbáljuk ezt a verem típust.
A Java programozási nyelv
Soós Sándor
14/24
A kivételkezelés megvalósítása Java-ban ●
A Java nyelv a következő utasításokat nyújtja a kivételkezeléshez: – – –
throw: kivétel kiváltása try-catch-finally: kivételkezelő blokk meghatározása throws: kivételek specifikálása
A Java programozási nyelv
Soós Sándor
15/24
A kivétel kiváltása Java-ban ●
●
Vagy a Virtuális Gép, vagy egy metódus válthatja ki a kivételt (throw utasítás). A throw paramétereként egy kivételosztályt kell megadni. Például: class UjException extends Exception { } throw new Exception( "Hiba történt!” ); throw new UjException();
●
A throw paramétereként csak olyan objektumot lehet megadni, ami kiváltható, azaz az osztálya a java.lang.Throwable osztály leszármazottja.
A Java programozási nyelv
Soós Sándor
16/24
A kivétel elkapása Java-ban ●
A kivételek elkapásához a vizsgálni kívánt utasításokat egy try blokkba kell tenni: try { // Java utasítások }
●
●
A try blokkban lévő utasításokat figyeli a JVM kivételek keletkezése szempontjából. Rajtunk múlik, hogy mekkora blokkokat alakítunk ki, tehetünk minden utasítást külön blokkba, vagy mindet egybe, és ezek között tetszőleges átmenet használható.
A Java programozási nyelv
Soós Sándor
17/24
A kivétel elkapása, folyt. ●
A try blokkban kiváltott kivételeket az utána következő catch blokk, vagy blokkok kezelik le: try { // java utasítások } catch(Típus1 változó1) { /* Java utasítások */ } catch(Típus2 változó2) { /* Java utasítások */ } catch(Típus3 változó3) { /* Java utasítások */ }
●
Minden catch ágban a "paraméterként" megadott típus határozza meg, hogy mely kivételeket képes lekezelni.
A Java programozási nyelv
Soós Sándor
18/24
A catch ágak sorrendje ●
●
●
A catch ágak sorrendje fontos, mert a megadott sorrendben keresi a JVM a megfelelő kezelőt. A kivételosztályok egymásra épülése miatt több blokk is alkalmas lehet. Ezek közül az elsőt választja a JVM. A Java fordítási hibát jelez, ha biztosan el nem érhető kódot talál. Ez a tény befolyásolja a catch ágak lehetséges sorrendjét.
A Java programozási nyelv
Soós Sándor
19/24
A finally blokk ●
Az utolsó catch blokk után megadható egy finally blokk. Az ebbe írt utasítások mindenképpen lefutnak, akkor is, ha – – –
●
nem lépett fel kivétel a kivételt valamelyik catch blokk lekezelte a kivételt egyik catch ág sem tudta lekezelni nem megfelelő típus miatt. Ekkor a hívó metódus kivételkezelő blokkjához kerül a vezérlés, de előtte lefut a finally blokk
Nézzük meg a FinallyTest.java példát!
A Java programozási nyelv
Soós Sándor
20/24
Egy teljes kivételfigyelő blokk try { // java utasítások } catch(Típus1 változó1) { /* Java utasítások */ } catch(Típus2 változó2) { /* Java utasítások */ } catch(Típus3 változó3) { /* Java utasítások */ } // ... finally { /* Java utasítások */ } ●
A try blokk után kötelezően következnie kell legalább egy catch vagy finally blokknak. Ha mindkettő van, akkor catch – finally sorrendben kell megadni őket.
A Java programozási nyelv
Soós Sándor
21/24
Kivételek specifikálása ●
Ha a programozó úgy dönt, hogy egy kivételt nem akar lekezelni az adott metódusban, hanem egy közvetett, vagy közvetlen hívójára hagyja azt, akkor a metódus fejében specifikálnia kell azt a throws kulcsszóval. metódus() throws Exception1, Exception2, ... { // ... }
●
●
Ha a metódus nem kezeli le a specifikált kivételt, akkor a JVM egy szinttel feljebb keres alkalmas kezelőt.
A Java programozási nyelv
Soós Sándor
22/24
Mikor érdemes specifikálni egy kivételt? ●
●
●
Van olyan eset, amikor a kivételt nem a kiváltó metódus szintjén lehet lekezelni, hanem feljebb. Például ha tele van a verem, akkor azt nem a verem tudja kezelni, hanem a vermet használó osztály. Ezért a Betesz metódus ne kezelje le a kivételt, hanem specifikálja azt.
A Java programozási nyelv
Soós Sándor
23/24
Klasszikus példa a Java nyelv specifikációjából ●
●
Nézzük meg a Teszt.java programot! Aki megértette a program működését, az valóban érti a Java kivételkezelő mechanizmusát.
A Java programozási nyelv
Soós Sándor
24/24