GhK FB 17 Mathematik / Informatik §6 Fehlerbehandlung mit Java Ausnahmen, Handling, Auswerfen GhK Fehlerbehandlung FB 17 Mathematik / Informatik • In jedem Programm kann es zur Laufzeit zu Fehlern kommen, die verschiedenste Ursache haben können, z.B.: – Falsches Eingabenformat – illegaler Speicherzugriff (zu hoher Array-Iindex etc.) – fehlende Resourcen (keine Datei, lesen am Dateiende etc.) • In Java werden solche Fehler als – Exception : Ausnahme, behebbarer Fehler – Error oder : fataler Fehler ausgeworfen und können dann im Programm ggf. abgefangen und entsprechend behandelt werden. • Java hat damit eine deutliche (optische) Trennung zwischen Programmablauf und Fehlerbehandlung. GhK Ausnahmen FB 17 Mathematik / Informatik //Ausnahmen.java import java.io.*; class Ausnahmen { public static void main(String[] args) {PrintWriter out = new PrintWriter(System.out, true); int i = Integer.parseInt(args[0]); out.println("i = " + i); } } • Die Deklaration von i kann aus zwei Gründen schiefgehen: – Ausnahmen ist ohne Parameter aufgerufen worden, d.h. args hat 0 Felder und es wird eine ArrayIndexOutOfBoundsException ausgeworfen. – Der erste Parameter von Ausnahmen ist nicht als Integer interpretierbar (z.B. "x1234") und es wird eine NumberFormatException ausgeworfen. GhK Ausnahmetypen FB 17 Mathematik / Informatik ClassNotFoundException CloneNotSupportedException IllegalAccessException InstantiationException Exception InterruptedException NoSuchFieldException NoSuchMethodException Throwable RuntimeException LinkageError Error VirtualMachineError ThreadDeath GhK ungeprüfte Fehler FB 17 Mathematik / Informatik • Java verlangt in der Regel, daß Fehlersituationen überprüft (abgefangen) werden müssen. Ausnahmen sind alle Errors und die RuntimeExceptions. • Ein LinkageError wie etwa AbstractMethodError, NOSuchFieldError oder NoSuchMethodError oder ein VirtualMachineError wie etwa OutOfMemoryError, StackOverflowError, InternalError oder UnknownError kann zur Laufzeit nicht sinnvoll aufgefangen werden und braucht es deshalb auch nicht. RuntimeException wie etwa ArithmeticException, NullPointerException, NumberFormatException, ArrayIndexOutOfBoundsException ist manchmal nur mit • Eine einem Aufwand aufzufangen, der den Nutzen nicht aufwiegt, darum braucht er nicht unbedingt behandelt zu werden. GhK Standard-Ausnahmebehandlung FB 17 Mathematik / Informatik • Java hat einen Standard-Ausnahmehandler, der den Typ der Ausnahme und die Reihenfolge der Methodenaufrufe, die zu dieser Ausnahme geführt haben (StackTrace) aus. d.h. nicht abgefangene Ausnahmen werden mit Programmabbruch bestraft! • Dies kann man auch explizit tun – out.print(e) gibt den Ausnahmetyp aus – e.printStackTrace() gibt die Methodenaufrufe aus • Ausnahmen können auch mit einem erklärenden Text versehen sein, der dann ausgegeben werden kann mit – out.println(e.getMessage()) GhK try-catch FB 17 Mathematik / Informatik • Um in Java eine Ausnahme abzufangen, die durch einen Befehl ***** ausgeworfen werden könnte, verwendet man das Schlüsselwort try {*****} . • Nach einer try-Klausel muß dann mindestens eine catchKlausel (Handler) folgen: – try { int i = Integer.parseInt(args[0]); out.println("i= "+i); } catch (NumberFormatException e) { out.print("Als erstes Kommandozeilen-Argument"); out.println("wird ein int-Wert benötigt !"); } catch (ArrayOutOfBoundsException e) { out.print("Aufruf in der Form :"); out.println("java <Programmname> <int-Wert>"): } GhK Beispiel FB 17 Mathematik / Informatik // Argumente.java import java.io.*; class Argumente { static PrintWriter out = new PrintWriter(System.out,true); static int n=0; public static void main(String[] args) { for (n=0;;n++) { try {out.println((n+1) + " : " + args[n]);} catch(ArrayIndexOutOfBoundsException e){break;} } out.println("****Ende der Argumentenliste****"); } } GhK geschachtelte try-Blöcke FB 17 Mathematik / Informatik • Das obige Beispiel könnte auch geschachtelt werden: – try {try { int i = Integer.parseInt(args[0]); out.println("i= "+i); } catch (NumberFormatException e) { out.print("Als erstes Kommandozeilen-Argument"); out.println("wird ein int-Wert benötigt !"); } } catch (ArrayOutOfBoundsException e) { out.print("Aufruf in der Form :"); out.println("java <Programmname> <int-Wert>"); } GhK finally-Block FB 17 Mathematik / Informatik • statt einer catch-Klausel oder nach allen catch-Klauseln darf noch ein Block finally {...} stehen, in der z.B. das Schließen von Dateien, Datenbanken, Netzverbindungen o.Ä. erledigt werden kann. • Der finally-Block wird in jedem Fall ausgeführt, gleichgültig ob: – keine Ausnahme ausgeworfen wird – der try-Block durch ein explizites return verlassen wird – eine Ausnahme ausgeworfen wird, die durch ein catch abgefangen wird – eine Ausnahme ausgeworfen wird, die nicht abgefangen wird GhK Regeln für try FB 17 Mathematik / Informatik • try-Blöcke können ineinander geschachtelt sein. • Wird in einem try-Block keine Ausnahme ausgeworfen, so werden alle unmittelbar danach stehenden catch-Blöcke (Handler) übersprungen. • Wird eine Ausnahme ausgeworfen, - so wird unter den nachfolgenden Handlern der erste ausgeführt, der auf die Ausnahme passt und alle darauffolgenden Handler werden übersprungen. - Wird kein passender Handler gefunden so wird hinter dem umfassenden try-Block nach ihm gesucht u.s.w. - Gibt es keinen umfassenden try-Block mehr, so wird der Standard-Ausnahmehandler eingesetzt (Dump + Abbruch). GhK throws-Klausel FB 17 Mathematik / Informatik • In einer Methodendeklaration kann nach dem Namen ein throws mit einer Liste von Typen stehen, die alle Subtypen von Throwable sein müssen. • Dies zeigt an, daß die Methode mit einer der in der Liste aufgeführten Ausnahmen abbrechen kann. • Die throws-Klausel muß stehen, wenn die ausgeworfenen Ausnahmen nicht vom Typ Error oder RuntimeException sind und nicht innerhalb der Methode abgefangen werden können oder sollen. • Mit diesem Mechanismus kann Java kontrollieren, ob alle Ausnahmen (außer Errors und RuntimeExceptions) auch abgefangen werden. GhK Hierarchie(1) FB 17 Mathematik / Informatik // Hierarchie.java import java.io.*; class Hierarchie { static PrintWriter out=new PrintWriter(System.out,true); static boolean superKlasse(Class cs, String t) // Fehler { Class ct = Class.forName(t); if (!cs.isAssignableFrom(ct)) return false; out.println(t + " ist Subklasse von " + cs); return true; } public static void main(String[] args) // Fehler { if (args.length == 0) {out.println("Start in der Form java Hierarchie <Name>" + "\n!!! voll qualifizierte Klassennamen !!!" + "\n(Z.B. java.io.FileNotFoundException)");return; } String s = args[0]; if (superKlasse(java.lang.Throwable.class, s)) if (superKlasse(java.lang.Exception.class, s)) {if (superKlasse(java.lang.RuntimeException.class, s));} else if (superKlasse(java.lang.Error.class, s)); } } GhK Hierarchie(2) FB 17 Mathematik / Informatik • Die Methode superKlasse kann in der Zeile Class ct = Class.forName(t) eine ClassNotFoundException auswerfen, wenn t kein gültiger Klassenname ist, darum wird superKlasse ohne den Zusatz throws ClassNotFoundException nicht übersetzt. • Die Methode main verwendet superKlasse, ohne die ClassNotFoundException abzufangen, daher muß auch sie mit dem Zusatz throws ClassNotFoundException versehen werden, damit sie übersetzt werden kann. • Regel: Exceptions müssen in einer Methode abgefangen oder mit einer throws-Klausel nach außen weitergereicht werden. GhK eigene Ausnahmen FB 17 Mathematik / Informatik • Jeder Programmierer kann natürlich auch eigene Ausnahmen aus Throwable oder deren Unterklassen ableiten. • Ausnahmen könne in einer Methode explizit mit dem Befehl throw .... ausgeworfen werden. • Regel: Werden Methoden aus Superklassen überschrieben, so darf die neue Methode nur solche Ausnahmen auswerfen, die die überschriebene Methode nach ihrer throws-Klausel auch hätte auswerfen können. Alle sonstigen Ausnahmen müssen innerhalb der Methode abgefangen werden. GhK Beispiel Throw FB 17 Mathematik / Informatik // Throw.java import java.io.*; import java.util.*; class Throw { static PrintWriter out = new PrintWriter(System.out, true); static class Closed extends Exception { ClosedShop(String text) { super(text);} } void connect() throws Closed { int tag = Calendar.getInstance().get(Calendar.DAY_OF_WEEK); if (tag == Calendar.SUNDAY) throw new Closed("sonntag"); if (tag == Calendar.THURSDAY)throw new Closed("donnerstag"); out.println("Heute normaler Betrieb."); } public static void main(String[] args) { try { new Throw().connect();} catch (Closed ex) { out.println( ex.getMessage() + "s geschlossen.");} } } GhK Passwortabfrage(1) FB 17 Mathematik / Informatik // Login.java import java.awt.*;import java.awt.event.*;import java.io.*; class Login extends Frame { TextField text; final int MAX = 5; int anz = 0; Login() // Konstuktor { super(" "); setLayout(new GridLayout(2, 1)); setFont(new Font("Monospaced", Font.PLAIN, 14)); add(new Label("Zum Starten Passwort eingeben")); add(text = new TextField(20)); text.setEchoChar('*'); text.setBackground(Color.darkGray); text.setForeground(Color.white); pack(); text.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {Frage();}}); setVisible(true);} class PasswdEx extends Exception { } GhK Passwortabfrage(2) FB 17 Mathematik / Informatik public static void main(String[] args) {new Login();} void Frage() { ++anz; try {try {if (!(text.getText().equals("Passwort"))) throw new PasswdEx(); //exit aus if.. dispose(); //Fenster zerstören new PrintWriter(System.out, true).println("Login ok"); System.exit(0);} catch (PasswdEx ex) {if (anz == MAX) throw ex; //exit aus try.. text.setEditable(false); text.setText(""); try {Thread.sleep(1000*anz);} catch (InterruptedException ign) { } text.setEditable(true);}} catch (PasswdEx ex) {new PrintWriter(System.out, true).println("Login fail"); System.exit(0);} //exit aus main }} GhK Passwortabfrage(3) FB 17 Mathematik / Informatik // LoginA.java import java.applet.*; import java.net.*; ... class LoginA extends Applet { TextField text,nachr; ... LoginA()// Konstuktor { //super(" "); ... //pack();} void Frage() {.... nachr.setEditable(false); nachr.setText("Login ok"); try {getAppletContext().showDocument // ruft eine URL auf (new URL("http://www.neuro.informatik.uni-kassel.de/"));} catch(java.net.MalformedURLException e){} GhK Zeichenfeld FB 17 Mathematik / Informatik // Scribble.java import java.applet.*;import java.awt.*; public class Scribble extends Applet { private int last_x = 0, last_y = 0 ; //zum Speichern von Punkten // Aufruf erfolgt beim Anklicken durch den Benutzer. public void mouseDown(Event e, int x, int y) { last_x = x; last_y = y;} //Position des Klicks merken // Aufruf erfolgt, wenn Maus mit gedrückter Taste bewegt wird public void mouseDrag(Event e, int x, int y) { Graphics g = getGraphics(); // in g wird gezeichnet g.drawLine(last_x, last_y, x, y); // Linie vom letzten Punkt zum aktuellen Punkt last_x = x ; last_y = y ;} } // Position aktualisieren GhK FB 17 Mathematik / Informatik • Dieses Applet erlaubt kleine Bilder mit der Maus zu zeichnen. Zeichenfeld(2)