350 likes | 492 Views
Ausnahmen. Was sind Programmfehler?. Programm erzielt gar kein Ergebnis. Berechnetes Ergebnis stimmt nicht mit dem erwarteten überein. Programm verhält sich falsch oder unzweckmäßig während der Abarbeitung, z.B.: Absturz bei falscher Eingabe unendliche Zyklen bei fehlerhaften Parametern
E N D
Ausnahmen DVG1 - Ausnahmen
Was sind Programmfehler? • Programm erzielt gar kein Ergebnis. • Berechnetes Ergebnis stimmt nicht mit dem erwarteten überein. • Programm verhält sich falsch oder unzweckmäßig während der Abarbeitung, z.B.: • Absturz bei falscher Eingabe • unendliche Zyklen bei fehlerhaften Parametern • kein Ende bei bestimmten Aufgaben • Programm arbeitet nicht reproduzierbar falsch DVG1 - Ausnahmen
Fehlerursachen • fehlerhafte Konzeption • fehlerhafter Algorithmus • fehlerhafte Syntax • fehlerhafte Realisierung der Konzeption bzw. des Algorithmus • fehlerhafte Bedienung bzw. fehlerhafte Parameter • Fehler innerhalb der VM • fehlerhaftes Betriebssystem • fehlerhafte Hardware DVG1 - Ausnahmen
Ausnahmen in JAVA • Befassen sich mit Fehlern, die zur Ausführungszeit eines Programms auftreten. Z.B.: • Ein-/Ausgabe-Fehler, z.B.: Lesefehler bei System.in.read(buffer); • Laufzeitfehler, z.B.: int i = Integer.parseInt(args[0]); führt bei args[0]=="abc" zu einer Ausnahme "NumberFormatException" • arithmetische Fehler, z.B.: int i = 1/0; führt zu einer Ausnahme "ArithmeticException" • JAVA bietet komfortable aber einfache Möglichkeiten zur Behandlung von Ausnahmen. DVG1 - Ausnahmen
public class test1 { public static void main ( String [] args) { int i = Integer.parseInt(args[0]); System.out.println("Es wurde der Wert "+i+" eingegeben."); } } "java test1 11234" ergibt: Es wurde der Wert 11234 eingegeben. "java test1 11234xx" ergibt: Exception in thread "main" java.lang.NumberFormatException: 11234xx at java.lang.Integer.parseInt(Compiled Code) at java.lang.Integer.parseInt(Integer.java:458) at test1.main(test1.java:5) DVG1 - Ausnahmen
Fehlerursache: 11234xx läßt sich nicht in eine int-Größe umwandeln! • Compilermeldung exakt und hilfreich für den Programmentwickler • Der Anwender wird durch die Meldung verunsichert und erfährt nicht, was er falsch gemacht hat. • Typischer Anruf des Anwenders: „Ich habe alles genau so gemacht wie immer, aber seit heute funktioniert nichts mehr. Was ist los?“ DVG1 - Ausnahmen
public class test2 { public static void main ( String [] args) { try { int i = Integer.parseInt(args[0]); System.out.println("Es wurde der Wert "+i+" eingegeben."); } catch (NumberFormatException e) { System.out.println(args[0]+ " kann nicht in eine int-Groesse verwandelt werden!\n"+ "Der Parameter darf nur aus Ziffern 0..9 bestehen!"); } } } "java test2 11234" ergibt: Es wurde der Wert 11234 eingegeben. "java test2 11234xx" ergibt: 11234xx kann nicht in eine int-Groesse verwandelt werden! Der Parameter darf nur aus Ziffern 0..9 bestehen! "java test2" ergibt: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at test2.main(test2.java:7) DVG1 - Ausnahmen
public class test3 { public static void main ( String [] args) { try { int i = Integer.parseInt(args[0]); System.out.println("Es wurde der Wert "+i+" eingegeben."); } catch (NumberFormatException e) { System.out.println(args[0]+ " kann nicht in eine int-Groesse verwandelt werden!\n"+ "Der Parameter darf nur aus Ziffern 0..9 bestehen!"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println( "Es muss mindestens ein Parameter angegeben werden!"); } } } "java test3" ergibt: Es muss mindestens ein Parameter angegeben werden! DVG1 - Ausnahmen
public class test4 { public static void main ( String [] args){ try { int i = Integer.parseInt(args[0]); System.out.println("Es wurde der Wert "+i+" eingegeben."); } catch (NumberFormatException e) { System.out.println(args[0]+ " kann nicht in eine int-Groesse verwandelt werden!\n"+ "Der Parameter darf nur aus Ziffern 0..9 bestehen!"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println( "Es muss mindestens ein Parameter angegeben werden!"); } finally { System.out.println( "Das Programm ist mehr oder weniger erfolgreich beendet."); } } } Egal wie das Programm beendet wird es gibt die Meldung aus: Das Programm ist mehr oder weniger erfolgreich beendet. DVG1 - Ausnahmen
Allgemeine Form try { // Block in dem Ausnahmen auftreten können } catch (Ausnahmetyp1 name) { // Block in dem der Ausnahmetyp1 behandelt wird } ... catch (AusnahmetypN name) { // Block in dem der AusnahmetypN behandelt wird } finally { // finally- Block } DVG1 - Ausnahmen
Nach einem try-Block muß immer mindestens ein catch-Block existieren. • Beim Eintreten einer Ausnahme wird der erste passende catch-Block abgearbeitet. • Der finally-Block muß immer nach allen catch-Blöcken stehen. • Der finally-Block wird abgearbeitet: • nach dem „normalen“ Ende des try-Blockes • nach einer behandelten Ausnahme • vor einer Ausnahme, die weitergereicht wird • nach Verlassen des try-Blockes über eine break-, continue- oder return-Anweisung DVG1 - Ausnahmen
Ausnahmetyp1 try-Block Ausnahme Catch-Block 1 Ausnahmetyp2 Catch-Block 2 AusnahmetypN Catch-Block N finally-Block DVG1 - Ausnahmen
public class test5 { public static void main (String [] args) { System.out.println("Gebe bitte eine Zeichenkette ein : "); byte [] buffer = new byte [80]; int ir=0; ir = System.in.read(buffer); if ((char)buffer[ir-1]=='\n') ir--; if ((char)buffer[ir-1]=='\r') ir--; String s = new String(buffer,0,ir); System.out.println("Es wurde eingegeben :\n\""+s+"\""); } } javac test5.java ergibt test5.java:8: Exception java.io.IOException must be caught, or it must be declared in the throws clause of this method. System.in.read(buffer); DVG1 - Ausnahmen
public class test6 { public static void main (String [] args) { System.out.println("Gebe bitte eine Zeichenkette ein : "); byte [] buffer = new byte [80]; int ir=0; try { ir = System.in.read(buffer); if ((char)buffer[ir-1]=='\n') ir--; if ((char)buffer[ir-1]=='\r') ir--; } catch (java.io.IOException e) { } String s = new String(buffer,0,ir); System.out.println("Es wurde eingegeben :\n\""+s+"\""); } } java test6 ergibt Gebe bitte eine Zeichenkette ein : Das ist ein Test. Es wurde eingegeben : "Das ist ein Test." DVG1 - Ausnahmen
geprüft bzw. ungeprüfte Ausnahmen • Ausnahmen NumberFormatExceptionundArrayIndexOutOfBoundsExceptionbrauchten nicht abgefangen zu werden, d.h. es mußte keine catch-Anweisung für diese Ausnahmen angegeben werden. ==> ungeprüfte Ausnahmen • Ausnahme java.io.IOException mußte abgefangen werden. ==> geprüfte Ausnahmen DVG1 - Ausnahmen
Ausnahmenhierarchie Error Exception ungeprüft geprüft ungeprüft Eigene Ausnahmen Eigene Ausnahmen nicht empfohlen meist benutzt RuntimeException IOException ungeprüft geprüft Eigene Ausnahmen Eigene Ausnahmen nicht empfohlen möglich Throwable DVG1 - Ausnahmen
Weiterreichen von Ausnahmen • Eine Ausnahme muß nicht in der Methode behandelt werden, in der sie auftritt. Sie kann auch an die aufrufende Methode weitergereicht werden. • Das wird dem Compiler durch die throws-Klausel einer Methoden-Deklaration mitgeteilt, z.B.: public static String readString() throws java.io.IOException DVG1 - Ausnahmen
public class test7 { public static String readString() { byte [] buffer = new byte [80]; try { int ir = System.in.read(buffer); if ((char)buffer[ir-1]=='\n') ir--; if ((char)buffer[ir-1]=='\r') ir--; return new String(buffer,0,ir); } catch (java.io.IOException e) { return null; } } public static void main (String [] args) { System.out.println("Gebe bitte eine Zeichenkette ein : "); System.out.println( "Es wurde eingegeben :\n\""+readString()+"\""); } } DVG1 - Ausnahmen
public class test8 { public static String readString() throws java.io.IOException { byte [] buffer = new byte [80]; int ir = System.in.read(buffer); if ((char)buffer[ir-1]=='\n') ir--; if ((char)buffer[ir-1]=='\r') ir--; return new String(buffer,0,ir); } public static void main (String [] args) throws java.io.IOException { System.out.println("Gebe bitte eine Zeichenkette ein : "); System.out.println( "Es wurde eingegeben :\n\""+readString()+"\""); } } DVG1 - Ausnahmen
Auslösen von Ausnahmen • Ausnahmen können durch das Programm ausgelöst werden, durch throw new Ausnahme (...); DVG1 - Ausnahmen
public class test9 { public static void main (String [] args) { int z = Integer.parseInt(args[0]); int n = Integer.parseInt(args[1]); if ( n == 0) { System.out.println("Der Nenner ist == 0 !"); throw new ArithmeticException("Nenner ist 0"); } else { System.out.println(z+"/"+n+"="+z/n); } } } java test9 1 0 ergibt Der Nenner ist == 0 ! Exception in thread "main" java.lang.ArithmeticException: Nenner ist 0 at test9.main(test9.java:11) DVG1 - Ausnahmen
Eigene Ausnahmen • Ausnahmen sind Klassen, die von anderen Ausnahmeklassen abgeleitet sind. • Einfachste Form: class Ausnahme extends OberKlasse { } z.B.: class Ausnahme extends Exception { } DVG1 - Ausnahmen
public class test10 { public static int f ( int z, int n ) throws Ausnahme { if ( n == 0 ) { throw new Ausnahme(); } return z/n; } public static void main (String [] args) { int z = Integer.parseInt(args[0]); int n = Integer.parseInt(args[1]); try { System.out.println(z+"/"+n+"="+f(z,n)); } catch (Ausnahme e) { System.out.println(e); } } } class Ausnahme extends Exception { } java test10 10 0 ergibt Ausnahme DVG1 - Ausnahmen
Lesemethoden • Was wollen wir einlesen? • Zeichenketten, Texte • numerische Daten • ganze Zahlen (byte, short, int, long) • Gleitkommazahlen (float, double) • Felder • Auswahlen, Menüs DVG1 - Ausnahmen
Einlesen von Zeichenketten • Probleme: • Eingabe ist gepuffert • es können beliebig lange Texte gelesen werden • Externe Darstellung von Zeichen im ASCII-Code • Interne Darstellung der Zeichen im Unicode • Möglichkeiten: • System.in.read(buffer,off,len) Lesen in byte-Puffer • System.in.available() wieviele Zeichen sind noch im Eingabepuffer • String(buffer,off,len) Umwandeln von ASCII-Zeichen in Unicode-Zeichen DVG1 - Ausnahmen
public static String readString() { try { byte [] buffer = new byte [80]; int ir = System.in.read(buffer); return new String(buffer,0,ir); } catch ( java.io.IOException e) { e.printStackTrace(); System.exit(1); return null; } } DVG1 - Ausnahmen
public static String readString() { try { byte [] buffer = new byte [80]; int ir = System.in.read(buffer); while ( (ir>0) && (buffer[ir-1]=='\n') | (buffer[ir-1]=='\r') ) ir--; return new String(buffer,0,ir); } catch ( java.io.IOException e) { e.printStackTrace(); System.exit(1); return null; } } DVG1 - Ausnahmen
public static String readString() { try { byte [] buffer = new byte [80]; int ir = System.in.read(buffer); if ( ir<=0 ) return ""; while ( (ir>0) && (buffer[ir-1]=='\n') | (buffer[ir-1]=='\r') ) ir--; return new String(buffer,0,ir); } catch ( java.io.IOException e) { e.printStackTrace(); System.exit(1); return null; } } DVG1 - Ausnahmen
public static String readString() { try { byte [] buffer = new byte [80]; int ir = System.in.read(buffer); if ( ir<=0 ) return ""; int ir2 = System.in.available(); if ( ir2>0 ) { byte [] sbuf = buffer; buffer = new byte [sbuf.length+ir2]; for (int i=0; i<sbuf.length;i++) buffer[i] = sbuf[i]; ir=System.in.read(buffer,sbuf.length,ir2)+sbuf.length; } while ( (ir>0) && (buffer[ir-1]=='\n') | (buffer[ir-1]=='\r') ) ir--; return new String(buffer,0,ir); } catch ( java.io.IOException e) { e.printStackTrace(); System.exit(1); return null; } } DVG1 - Ausnahmen
public static double readDouble ( ) { for (;;) { try { String s = readString(); return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print("Nochmal:"); } }} DVG1 - Ausnahmen
public static double readDouble ( ) { for (;;) { try { String s = readString(); if ( s.compareToIgnoreCase("nan")==0 ) return 0.0/0.0; return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print("Nochmal:"); } }} DVG1 - Ausnahmen
public static double readDouble ( double def ) { for (;;) { try { String s = readString(); if ( s.compareToIgnoreCase("nan")==0 ) return 0.0/0.0; if ( s.length() == 0 ) return def; return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print("Nochmal:"); } }} DVG1 - Ausnahmen
public static double readDouble ( String prompt, double def, String colon) { System.out.print(prompt+" ["+def+"] "+colon); for (;;) { try { String s = readString().trim(); if ( s.compareToIgnoreCase("nan")==0 ) return 0.0/0.0; if ( s.length() == 0 ) return def; return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print("Nochmal ["+def+"] "+colon); } }} DVG1 - Ausnahmen
public static double readDouble ( String prompt, String errorMessage, double def, String colon) { System.out.print(prompt+" ["+def+"] "+colon); for (;;) { try { String s = readString().trim(); if ( s.compareToIgnoreCase("nan")==0 ) return 0.0/0.0; if ( s.length() == 0 ) return def; return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print(errorMessage+" ["+def+"] "+colon); } }} DVG1 - Ausnahmen
public static double readDouble ( String prompt, String errorMessage, double def, String colon) { String helpText = "Geben Sie bitte eine double-Groesse ein.\n"+ "Die Eingabe darf aus den Ziffern 0..9 bestehen. Ausserdem koennen\n"+ "ein Dezimalpunkt, das Zeichen \"E\" fuer den Exponenten,\n"+ "sowie Vorzeichen vor der Zahl und dem Exponenten angegeben werden.\n"+ "NaN erhaelt man durch Eingaben von \"NaN\".\nz.B.: -1.234567E-123"; System.out.print(prompt+"(?=help) ["+def+"] "+colon); for (;;) { try { String s = readString().trim(); if ( s.compareTo("?")==0 ) { System.out.println(helpText); System.out.print(prompt+"(?=help) ["+def+"] "+colon); continue; } if ( s.compareToIgnoreCase("nan")==0 ) return 0.0/0.0; if ( s.length() == 0 ) return def; return Double.parseDouble(s); } catch ( NumberFormatException e ) { System.out.print(errorMessage+"(?=help) ["+def+"] "+colon); } }} DVG1 - Ausnahmen