Exception Handling in Java Seminar aus Softwareentwicklung Norbert Wiener Ziele von Exception Handling Programme robuster machen gegen: • fehlerhafte Eingaben • Gerätefehler (Defekte, Platte voll, ...) • Programmierfehler (z.B. Division durch 0) Trennung zwischen Algorithmus und Fehlerbehandlung Fehlerbehandlung durch Compiler überprüfbar machen Auslösen von Exception explizite Ausnahmen: „throw“ Anweisung im Code. setPassword(String pw) { ...... } if(pw.length() < 5) throw new Exception(„mind. 5 Zeichen“); ....... implizite Ausnahmen durch die JVM - Divison durch 0 => ArithmeticException - Zugriff über null-Ref. => NullPointerException - Ungültige Konvertierung => ClassCastException int intDiv (int i, int j) { return i/j; } try-catch-finally Syntax try { Anweisungen; } catch (Ausnahme1 a1) { Fehlerbehandlung1; } catch (Ausnahme2 a2) { Fehlerbehandlung2; } finally { Aufräumen; } Nach einem try-Block muss mindestens ein catch-Block folgen! Der finally-Block ist optional Bei mehreren catch-Blöcken beginnt die Suche der Ausnahmenbehandlung von oben nach unten. Beispiel class Catch{ public static void main(String[] args){ try{ int i = Integer.parseInt(args[0]); System.out.print("i= "+i); }catch(ArrayIndexOutOfBoundsException e){ System.out.print("Parameter vergessen!"); }catch(NumberFormatException e){ System.out.print(" kein int-Wert!"); }finally{ System.out.println(" finally!"); } } } Catch 123 i= 123 finally! Catch xy kein int-Wert! finally! Catch Parameter vergessen! finally! Finally wird immer ausgeführt! Ausnahme-Klasse definieren class MyException extends Exception{ } class MyException extends Exception{ public MyException() { super(); } public MyException(String msg) { super(msg); } } Eigener Exceptiontyp (indirekt) von Throwable ableiten. Konstuktor ohne Parameter Konstruktor mit Fehlermeldung Die throws-Klausel setPassword(String pw) { try{ if(pw.length() < 5){ throw new Exception(„Fehler“); } }catch(Exception e){ Ausnahme behandeln! } } Weitergabe der Exception an die aufrufende Methode Try{ setPassword(pw); }catch(Exception e){ Ausnahme behandeln! } static setPassword(String pw) throws Exception { if(pw.length() < 5){ throw new Exception(„Fehler“); }....... } throws Beispiel ..Main(...){ ...... try{ A(x); }catch(Exc1 e){ ..print("Main"); } ........ C(int x) ........ ........ A(int x) B(int x) throws Exc1, Exc2 ,Exc3 { throws Exc1{ throws Exc1, Exc2{ try{ try{ if(x==1){ try{ B(x); throw new Exc1("F."); C(x); }catch(Exc2 e){ }catch(Exc3 e){ ...println("A"); ...println("B"); }finally{ }else if(x==2){ throw new Exc2(); }else if(x==3){ }finally{ ..println("finA") throw new Exc3(); ...println("finB"); } }else{ } } throw new Exc4(); } } x=1 x=2 x=3 x=4 finB finB B C finA A finB finB Main finA finA finA }catch(Exc4 e){ ....println("C"); } } Debugging von Ausnahmen class Test{ static int x =1; e.getMessage() e.printStackTrace() public static void main(String args[]) { try{ A a= new A(x); }catch(Exc1 e){ System.out.println("Main"); System.out.println(e.getMessage()); e.printStackTrace(); } } } finB finA Main Fehler! Exc1: Fehler! at C.<init>(C.java:6) at B.<init>(B.java:4) at A.<init>(A.java:4) at Test.main(Test.java:6) Klassenhierarchie Throwable Error Exception VirtualMachineError LinkageError RuntimeException IOException OutOfMemoryError NoSuchFieldError NullpointerException FileNotFoundException unchecked checked Die Error-Klasse VirtualMachineError InternalError OutOfMemoryError StackOverflowError UnknownError LinkageError NoSuchMethodError NoSuchFieldError AbstraktMethodError ThreadDeath Ausnahmen des Typs Error sind nicht vernünftig zu behandeln. Die Exception Klasse IOException FileNotFoundException SocketException EOFException RemouteException UnknownHostException InterruptedException NoSuchFieldException ClassNotFoundException NoSuchMethodException Diese Exception müssen behandelt werden! (ausgenommen RuntimeException) Exception auf ByteCode Ebene void f() { try { throw new Exception(); } catch (Exception e) { System.out.println(e); } } 0 3 4 7 8 9 12 13 16 new #2 <Class Exception> dup invokespecial <init> athrow astore_1 getstatic out:System aload_1 invokevirtual println return Exception e; e = new Exception(); throw e; Adr.-> Exception Adr.-> Exception Operanden-Stack Objekt im Speicher allokieren Objektreferenz auf OperantenStack Referenzadresse wird dupliziert Konstruktor wird ausgeführt Exception Table: From 0 To Target 8 8 Type Exception Beispiel static int remainder(int dividend, int divisor) throws OverflowException, DivideByZeroException { if ((dividend == Integer.MIN_VALUE) && (divisor == -1)) { throw new OverflowException(); } try { return dividend % divisor; } catch (ArithmeticException e) { throw new DivideByZeroException(); } } Exception Handling wird an die Vorgängermethode delegiert! Beispiel static int remainder(int dividend, int divisor) throws OverflowException, DivideByZeroException { if ((dividend == Integer.MIN_VALUE) && (divisor == -1)) { throw new OverflowException(); } try { return dividend % divisor; } catch (ArithmeticException e) { throw new DivideByZeroException(); } } Exception Table: From To Target 19 23 23 Type ArithmeticException 0 1 3 6 7 8 iload_0 ldc #1 <Integer - 2147483648> if_icmpne 19 iload_1 iconst_m1 if_icmpne 19 11 new #4 <Class OverflowException> 14 dup 15 invokespecial #10 <Method OverflowException()> 18 athrow 19 20 21 22 23 24 27 28 iload_0 iload_1 irem ireturn pop new #2 <Class DivideByZeroE.> dup invokespecial #9 <Method DivideByZeroException()> 31 athrow Danke für die Aufmerksamkeit