Most azt vizsgáljuk meg hogy mi van akkor ha valami előre nem látott probléma, hiba közbejön? Hogyan kezeljük le ezeket a kivételes eseteket?
Erre a problémára ad megoldást a kivételkezelés. A kivételeket le tudjuk kezelni a program futása közben, amennyiben felkészítjük a kódunkat arra, hogy a gyanús esteket figyeljék. Ilyen eset lehet például egy fájl megnyitásakor az hogy van-e egyáltalán engedélyünk arra, hogy a fájlhoz hozzáférjünk, létezik-e egyáltalán az adott fájl stb. Ilyenkor a kritikus műveleteket egy megfelelő szintaktikai elemmel közre tudjuk fogni és ha hiba keletkezik, akkor azt el tudjuk kapni és le tudjuk kezelni.
A nyelvi eszköz erre az úgynevezett try-catch-finally blokk. A try után álló utasításblokkba kell foglalni a kritikus utasításokat, melyek kivételt generálhatnak (kivétel "dobhatnak"). A try blokk után azonnal következnie kell legalább egy catch blokknak. Ugyanis ha kivétel generálódik a try blokkban akkor a létrejövő kivételobjektum átadódik a catch blokknak és ott szépen le tudjuk kezelni a problémát. Több catch blokk is lehet, ugyanis többféle kivétel (Exception) létezik és mi magunk is tudunk definiálni ilyeneket.
A catch blokk(ok) után következhet egy finally blokk (nem kötelező). Ez a blokk minden esetben megkapja a vezérlést, akár volt kivétel akár nem, akár elkaptuk akár nem. Ebben szokás erőforrásokat felszabadítani, fájlokat lezárni stb....
Amikor valami rendellenes probléma kivétel dob (throw) egy metódus futása közben, akkor létrejön kivétel objektum (Exception) ami információt hordoz a hibáról, a futtató környezetről és a programunk állapotáról. Ha hiba keletkezik akkor a futtató környezet elkezd keresni először az adott metódusban, majd az őt hívó metódusban (ha van ilyen) stb, egy olyan kivétel kezelő blokkot ami le tudja kezelni a keletkezett kivételt. Ha nem talál ilyet akkor a program végrehajtása megszakad és a JVM kapja meg a kivételt, ami ki is írja a problémát (de a programunk nem fut tovább). Ezért inkább próbáljunk meg felkészülni és elkapni a kivételeket.
Még nem beszéltünk a Java standard gyári csomagokról. Egyenlőre annyit kell tudni róluk, hogy különféle problémákra léteznek gyári megoldások, melyek segítenek a programozói munkába. Ezek kb a procedúrális nyelvek rutinkönyvtárainak felelnek meg, csak itt egy osztályhierarchiáról van szó. Nézzük ennek egy szeletét, mégpedig a kivételek (Exception) hierarchiát:
A fenti diagramból látható hogy milyen sokféle kivétel lekezelésére tud objektum generálódni.
Mi magunk is tudunk generálni kivételt a throw utasítással. Ilyenkor meg kell mondanunk hogy milyen kivételt akarunk dobni.
Most nézzünk erre egy példát.
Tegyük fel, hogy a Haromszog osztályunkat szeretnénk úgy módosítani, hogy a konstruáláskor ellenőrizzük hogy a megadott oldalhosszakkal lehet-e egyáltalán háromszöget rajzolni.
Ehhez ismét hívunk egy matematikust szakértőnek, aki elárulja hogy egy háromszög akkor létezik, ha bármely két oldalának összege nagyobb a harmadik oldalnál. Tehát ha nem teljesül a a>b+c és b>a+c és c>a+b ellenőrzés akkor kivételt generálunk, így nem jön létre a Haromszog objeltum.
Írjuk át a konstruktor a következőképp:
public Haromszog(double a, double b, double c){
if ((a<b+c) && (b<a+c) && (c<a+b)) {
this.a=a;
this.b=b;
this.c=c;
} else {
throw new IllegalArgumentException("Ezekkel az oldalhosszakkal nem rajzolható háromszög ("+a+"; "+b+"; "+c+")");
}
}
Így már csak akkor inícializálódnak az objektum tulajdonságai (oldalhosszai) ha szerkeszthető háromszög a megadott adatokkal. Ha nem akkor dobunk egy IllegalArgumentException kivételt, amit a tesztelő programunkban a következőképp tudunk elkapni:
1: public class SikidomTest {
2:
3: public static void main(String[] args) {
4:
5: Haromszog h1=null;
6: try {
7: h1=new Haromszog(2, 3, 6);
8: } catch(IllegalArgumentException e) {
9: System.out.println(e.getMessage());
10: }
11:
12: if (h1==null) {
13: System.out.println("A háromszög nem létezik!");
14: } else {
15: System.out.println("A háromszög létezik! Területe: " + h1.terulet());
16: }
17:
18: }
19:
20:
A 6 - 10 sorok között látható a kivételkezelés szintaktikai szerkezete. A fenti példa eredményeként nem fog létrejönni az objektum, így null érték lesz a referencia, amivel a későbbiekben vezéreljük a kiíratást.