Ez az oldal tartalmazza a könyvben előforduló kivételkezelési példák forrását és a hozzájuk tartozó magyarázatokat.
Új kivételosztály létrehozása és a program egy más pontján
kivételek kiváltása.
class MyException extends Exception { } //... throw new Exception("Valamilyen hiba!"); throw new MyException(); //...A teljes program: kivetel1.java |
A példában két új kivételosztály jön létre, melyet Verem típusú
objektumok váltanak ki. A VeremMegteltException -t akkor, ha a fix
méretű verembe már nem fér több elem. Ekkor a kimaradó elem a
kivételen keresztül a kezelőhöz is eljut, és a miVolt metódussal
lekérdezhető.
class VeremException extends Exception { } class VeremMegteltException extends VeremException { private Object utolsó; public VeremMegteltException(Object o) { utolsó=o; } public Object miVolt(){ return utolsó; } } class Verem { final static public int MÉRET=10; private Object tároló[]=new Object[MÉRET]; private int mutató=0; //... public void betesz(Object o) { //... if( mutató<tároló.length ) { tároló[mutató++]=o; } else { throw new VeremMegteltException(o); } //... } } }A teljes program: Verem1.java |
A try blokk figyeli a benne szereplő utasításokat kivétel
keletkezése szempontjából. A catch ágak elkapják a
paraméterüknek megfelelő típusú kivételt és végrehajtják az
ághoz tartozó utasításokat.
try { /*Java utasítások*/ } catch(Típus1 változónév1) { /*Java utasítások*/ } catch(Típus2 változónév2) { /*Java utasítások*/ } catch(Típus3 változónév3) { /*Java utasítások*/ } //...A teljes program: kivetel2.java |
Fontos jól megválasztani a kivételkezelő ágak sorrendjét, a
speciálisabbtól az általánosabb felé haladva.
class VeremException extends Exception { } class VeremMegteltException extends VeremException { } class ListaException extends Exception { } try { /*...*/ } catch(VeremMegteltException v1) { /*...*/ } catch(VeremException v2) { /*...*/ } catch(Exception v3) { /*...*/ }A teljes program: Verem2.java |
Az alábbi fájlmegnyitási példa jól szemlélteti a finally
használatának szükségességét. Ha az out megnyitásra
került, akkor bármelyik lefutásnál lezáródik.
FileOutputStream out = null; int data = 1; try { out = new FileOutputStream("kimenet.txt"); out.write(data); out.flush(); } catch (IOException e) { System.out.println("Fájl írási hiba!"); } finally { if (out != null) { try { out.close(); } catch( IOException ioe) { System.out.println("Lezárási hiba!"); } } }A teljes program: finally.java |
A korábbi vermes példa kiegészítése a
VeremMegteltException elkapásával.
public void betesz(Object o) { try{ if( mutató<tároló.length ) { tároló[mutató++]=o; } else { throw new VeremMegteltException(o); } } catch(VeremMegteltException e) { System.out.println("A(z) "+e.miVolt()+" objektum nem fért a verembe!"); } catch(Exception e) { System.out.println("Valamilyen hiba történt!"); } finally { System.out.println("A betesz metódus lefutott!"); } }A teljes program: Verem1.java |
Az alábbi példában szereplő catch ág minden
kivételt elkap, de semmit nem kezd velük. Így a felhasználó nem
értesül a hibáról, amikor az bekövetkezik.
public void f(Object o) { try{ // időnként kivételt okozó műveletek } catch(Exception e) { } }A teljes program: kivetel3.java |
Ha a metódus írója nem tud vagy nem akar mit kezdeni a fellépő
kivételekkel, akkor specifikálja azokat.
metódus() throws Exception1, Exception2, ... { //... }A teljes program: kivetel4.java |
Mivel egy általános verem esetén a verem felhasználója tudja,
hogy mit kell tenni betelés esetén, ezért jobb specifikálni, és
nem elkapni a keletkező kivételeket.
public void betesz(Object o) throws VeremMegteltException { //... if( mutató < tároló.length ) { tároló[mutató++]=o; } else { throw new VeremMegteltException(o); } //... }A teljes program: Verem3.java |
Az alábbi példa a kivételkezelés összes elemét felvonultatja:
kiváltás, terjedés, elkapás, kezelés, specifikálás.
class MyException extends Exception { public MyException(String s) { super(s); } } class Teszt { static int dobo(String s) throws MyException { try { if (s.equals("osztas")) { int i = 0; return i/i; } if (s.equals("null")) { s = null; return s.length(); } if (s.equals("teszt")) { throw new MyException("Teszt üzenet"); } return 0; } finally { System.out.println("[dobo(\"" + s +"\") vége]"); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { try { dobo(args[i]); System.out.println("Teszt \""+ args[i]+ "\" nem váltott ki kivételt"); } catch (Exception e) { System.out.println("Teszt \""+ args[i]+ "\" kiváltott egy kivételt: "+ e.getClass()+"\n "+ e.getMessage()+" üzenettel"); } } } }A teljes program: Teszt.java |
Az alappélda, amit hibakezeléssel kétféleképpen is kibővíthetünk.
gyumolcs() { alma(); //meghívott eljárások //... korte(); //... barack(); }A teljes program: kivetel5.java |
A hagyományos kezelési mód megnöveli a kódot, és
áttekinthetetlenné teszi.
gyumolcs() { ret1=alma(); if(ret1==ok) { //... ret2=korte(); if(ret2==ok) { //... ret3=barack(); if(ret3==ok) { return ok; } else { /* barack hibakezelése */ } } else { /* korte hibakezelése */ } } else {/* alma hibakezelése */ } }A teljes program: kivetel6.java |
Kivételkezeléssel a kód növekedése kisebb, és ami még fontosabb
a kód sokkal áttekinthetőbb.
class AlmaException extends Exception {} class KorteException extends Exception {} class BarackException extends Exception {} gyumolcs() { try { alma(); korte(); barack(); } catch(AlmaException hiba1) { /* alma hibakezelése */ } catch(KorteException hiba2) { /* korte hibakezelése */ } catch(BarackException hiba3) { /* barack hibakezelése */ } }A teljes program: kivetel7.java |
Az alappélda, amit hibaterjesztéssel kétféleképpen is kibővíthetünk.
gyumolcs() { alma(); //folytatás1 } alma() { jonatan(); //folytatás2 } jonatan() { //műveletek }A teljes program: kivetel8.java |
A hagyományos hibaterjesztés elbonyolítja a kódot és olyan részt
is érint, amit nem volna szükséges.
gyumolcs() { ret=alma(); if(ret!=ok) { //hibakezelés } else { //folytatás1 } } alma() { ret=jonatan(); if(ret!=ok) { return hiba; } else { //folytatás2 } } jonatan() { //műveletek if( művelethiba ) return hiba; }A teljes program: kivetel9.java |
A kivételkezelés elegáns módot ad a hibaterjesztésre.
gyumolcs() { try { alma(); //folytatás1 } catch(VmiException) { //hibakezelés } } alma() throws VmiException { jonatan(); //folytatás2 } jonatan() throws VmiException { //műveletek }A teljes program: kivetel10.java |
A kivételosztályok használatával nem kell rejtélyes hibakódokat
használni, és a hibáról is több tudható meg.
class VeremException extends Exception {} class VeremMegteltException extends VeremException {} class VeremUresException extends VeremException {}A teljes program: Verem4.java |