Na még egy fura angol szó! De ez már csak ilyen, a világ jó része angolul van, és ezeknek a kifejezéseknek a magyar fordítása méginkább talányos. Dobjunk egy kivételt? Huhh, ez sem sokat segít, szóval engedd, hogy megmagyarázzam.
Egy program általában békességgel és boldogsággal fut, de lehet, hogy olyan dolgot kérünk tőle, amit nem tud megcsinálni. Például, megkérjük, ossza el a kettőt nullával!
public class ExceptionPelda {
public static void main(String[] args) {
int a=2;
int b=0;
int c=a/b;
System.out.println("Az osztas eredmenye"+c);
};
}
Feladat: mit ír ki ez a program?
Vajon mi az eredmény? Nulla? Végtelen? Vagy micsoda? Igaziból itt nincs jó eredmény, mert a nullával való osztás nem hajtható végre. A program két dolgot csinálhat:
Nos, a helyzet az, hogy az elsunnyogás gonosz dolog lenne, mert lehet, hogy utána még további számításokat csinálunk, amik mind-mind hibásak lesznek, hiszen a c értéke is hibás volt. Utána napokig kutathatjuk, hogy vajon miért és hol romlott el az egész.
A helyes megoldás azonnal megállni.
Ha már megállunk, segítene az is, hogyha kapnánk egy hibaüzenetet, és egy kis infót hogy melyik sorban volt a hiba.
Egy olyan kivételes eset (általában nem várt hiba), ami miatt a program végrehajtása nem folytatódhat értelmesen.
Bármikor, amikor valami olyan dologhoz ér a program, ami nem hajtható végre. Például, megnyitunk egy file-t, de nincs is olyan nevű file. Vagy éppen az Interneten akarunk csinálni valamit, de nincs hálózati kapcsolat. Sok-sok ilyen ok létezhet, és ezek mind-mind exceptionban végződnek.
De a legjobb, hogy mi is csinálhatunk egy exception-t. Az Exception is természetesen egy objektum-osztály. Sőt, ebből származik mindenféle további Exception, mint például a matek hiba exception, vagy a nincs meg a file (FileNotFoundException).
A mi céljainkra a RuntimeException a legjobb, ez az őse mindennek, ami "csak úgy" váratlanul történhet menet közben. Mivel ez egy objektum-osztály, csak csinálunk belőle egy példányt, és van olyan konstruktora, amibe egy szöveget lehet megadni, ami a hiba szövege lesz:
RuntimeException exception=new RuntimeException("Jajjaj!");
Na de ettől még semmi sem történik. Attól még hogy létrehozunk egy objektum-példányt, nem fog megállni a program futása, nem igaz?
Az exception-t egy jó rugással kell útjára bocsátani. Ezt a műveletet nevezik az exception dobásának, mert az ehhez való kulcsszó a throw ami dobást jelent.
A throw után kell írni egy exception példányt, szóval összerakva így néz ki:
public class ExceptionPelda {
public static void main(String[] args) {
int a=2;
int b=0;
throw new RuntimeException("Jujujj!");
};
}
Hogy ez mire jó? Arra, hogy megállítja a program futását valami értelmes üzenettel.
Később pedig ezt a hibát esetleg magunk tudjuk lekezelni, valami értelmes módon. Például, ha egy webböngészőt csinálunk, és egy internetes kommunikáció exception-t dob, akkor ahelyett hogy az egész böngésző megállna egy hibával, kirakunk egy kedves ablakot, hogy sajnos most ez nem fog menni, mert nincs net.
Régen, a C nyelv idejében nem voltak exception-ök. Egyetlen módja a hibák kikerülésének az volt, hogyha állandóan nagyon figyeltünk, és mi állítottuk meg a program futását. Persze Java-ban is lehet ilyen csúnyán programozni:
public class ExceptionPelda {
public static void main(String[] args) {
int a=2;
int b=0;
// kézzel védekezünk a hibák ellen
if (b==0) {
System.out.println("Ez nullaval valo osztas!");
System.exit(0);
}
int c=a/b;
System.out.println("Az osztas eredmenye"+c);
};
}
Ez a megoldás nem igazán ipari.
Ezek ellen találták ki az exception-öket. Merthogy az exception-ök dobódnak, és megállítják a program futását ha valamit nem lehet végrehajtani.
Igazán nem jó, ha minden egyes exception megállítja a programot. Az biztos, hogy valami mást kell csinálni hiba esetén, de a program megállítása azért elég durva lépés. Képzeld csak el, hogy mondjuk Wordben leraksz egy alakzatot, majd ennek át akarod írni a méretét, és véletlen üresen hagyod a mezőt. Az üres az nem szám - szóval ott lesz egy exception - de azért ettől nem kellene a Wordnek megállnia mindenestül, úgy hogy még a dokumentumodat sem menti el, csak kilép, ugye?
Szóval, a hibákra fel lehet készülni, és le lehet őket kezelni. Egy speciális utasításblokk, amit a try kulcssszóval kezdesz, megpróbálja a benne lévő kódot végrehajtani. Ha valami exception lép fel, akkor a hozzátartozó catch blokkon folyatódik a program. A catch blokk megkapja paraméterként az exception-t, így ha akarjuk, még a hibaszöveget is kiolvashatjuk belőle. Ebben a példában csak egy értelmesebb üzenetet írunk a kérpernyőre, ha az osztás során bármi hiba lépett fel.
A catch azt jelenti, hogy elkapni. Ha elkaptuk az exception-t, akkor utána a catch blokk után folytatódik a program végrehajtása. Ha nem kaptuk el az exception-t, akkor az "tovább dobódik", és ha senki sem kapja el, akkor megállítja a programot.
Ebben a példában csak az ArithmeticException-t (és esetleges leszármazottait) kapjuk el. Ha esetleg a try.. blokkban lenne egy kis file-kezelés és az file not found exception-t dobna, az ugyanúgy tovább dobódik, és mivel semmiféle catch-ot nem tettünk erre, megállítaná a programot.
public class ExceptionPelda {
public static void main(String[] args) {
int a=2;
int b=0;
try {
int c=a/b;
System.out.println("Az osztas eredmenye"+c);
} catch (ArithmeticException e) {
System.out.println("Sajnos nem számolható ki a kifejezás értéke.");
}
System.out.println("A program itt folytatódik...");
};
}
Az egészben az a szép, hogy a normális programvégrehajtás (azaz a try blokk belseje) és az esetleges hibák lekezelése (azaz a catch blokk) egymástól jól elkülönül.
Nem kell száz if-el ellenőrizgetni egy bonyolult számításhoz tartozó részeredményeket, hanem egyszerűen megpróbáljuk (angolul try) elvégezni a számítást úgy ahogy van. Ha sikerül, örülünk. Ha nem sikerül, akkor ráérünk valami jó kis hibajelzést produkálni, vagy kitalálni, hogy hogyan tovább, amikor elkapunk (angolul catch) egy exceptiont a catch blokkban.
Mivel két utasításblokkra különül el a helyes és a hibás irány, ezért nevezik ezt struktúrált hibakezelésnek. Ami struktúrált, ott utasításblokkok vannak, ugye emlékszel még?