380 likes | 509 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 DVG2 - 04
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 DVG2 - 04
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 DVG2 - 04
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. DVG2 - 04
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) DVG2 - 04
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?“ DVG2 - 04
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) DVG2 - 04
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! DVG2 - 04
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. DVG2 - 04
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 } DVG2 - 04
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 DVG2 - 04
Ausnahmetyp1 try-Block Ausnahme Catch-Block 1 Ausnahmetyp2 Catch-Block 2 AusnahmetypN Catch-Block N finally-Block DVG2 - 04
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); DVG2 - 04
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." DVG2 - 04
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 DVG2 - 04
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 DVG2 - 04
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 DVG2 - 04
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()+"\""); } } DVG2 - 04
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()+"\""); } } DVG2 - 04
Auslösen von Ausnahmen • Ausnahmen können durch das Programm ausgelöst werden, durch throw new Ausnahme (...); DVG2 - 04
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) DVG2 - 04
Eigene Ausnahmen • Ausnahmen sind Klassen, die von anderen Ausnahmeklassen abgeleitet sind. • Einfachste Form: class Ausnahme extends OberKlasse { } z.B.: class Ausnahme extends Exception { } DVG2 - 04
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 DVG2 - 04
Für eigene Ausnahmen sollten die Konstruktoren definiert werden, da nur der „leere Konstruktor“ automatisch erzeugt wird. public class Ausnahme extends Exception { Ausname() { super() } Ausnahme(String message) { super(message) } } • Bei dieser Form kann eine Nachrichtentext den Fehler genauer erläutern bzw. lokalisieren. DVG2 - 04
Beispiel : Skalarprodukt static double ScalarProduct(double [] x, double [] y) { double sp=0.0; for (int i=0;i<x.length;i++) sp+=x[i]*y[i]; return sp; } DVG2 - 04
Zusammenfassung Aktivieren von Ausnahmen throw new NameDerAusnahme ("Fehlermeldung",...); DVG2 - 04
static double ScalarProduct(double [] x, double [] y) { if (x==null) throw new NullPointerException("erster Parameter null"); if (y==null) throw new NullPointerException("zweiter Parameter null"); double sp=0.0; for (int i=0;i<x.length;i++) sp+=x[i]*y[i]; return sp; } DVG2 - 04
Definition von Ausnahmen [public] class NameDerAusnahme extends Exception { NameDerAusnahme() { super(); } NameDerAusnahme(String message) { super(message); } [weitere Konstruktoren, Attribute, Methoden] } DVG2 - 04
Beispiel : eigene Ausnahme public class DimensionException extends Exception { DimensionException() { super(); } DimensionException(String message) { super(message); } } DVG2 - 04
static double ScalarProduct(double [] x, double [] y) { if (x==null) throw new NullPointerException("erster Parameter null"); if (y==null) throw new NullPointerException("zweiter Parameter null"); if (x.length != y.length) throw new DimensionException ( "Ungleiche Dimension der Felder im Skalarprodukt"); double sp=0.0; for (int i=0;i<x.length;i++) sp+=x[i]*y[i]; return sp; } DVG2 - 04
Weiterreichen von Ausnahmen ... NamederMethode (...) throws NameDerAusnahme1, NameDerAusnahme2,..., NameDerAusnahmeN DVG2 - 04
static double ScalarProduct(double [] x, double [] y) throws DimensionException { if (x==null) throw new NullPointerException("erster Parameter null"); if (y==null) throw new NullPointerException("zweiter Parameter null"); if (x.length != y.length) throw new DimensionException( "Ungleiche Dimension der Felder im Skalarprodukt"); double sp=0.0; for (int i=0;i<x.length;i++) sp+=x[i]*y[i]; return sp; } DVG2 - 04
Beispiel : Matrix x Vektor static double [] MatrixVektor(double[][]A, double[]x) { double [] y = new double[A.length]; for (int i=0;i<y.length;i++) { y[i]=ScalarProduct(A[i],x); } return y; } DVG2 - 04
Abfangen von Ausnahmen try { // Anweisungen im try-Block } catch (NameDerAusnahme1 e) { // Anweisungen im ersten catch-Block } ... catch (NameDerAusnahmeN e) { // Anweisungen im N-ten catch-Block } finally { // Anweisungen im finally-Block } DVG2 - 04
Beispiel : Matrix x Vektor static double [] MatrixVektor(double[][]A, double[]x) throws DimensionException { if (A==null) throw new NullPointerException("erster Parameter null"); if (x==null) throw new NullPointerException("zweiter Parameter null"); double [] y = new double[A.length]; for (int i=0;i<y.length;i++) { if (A[i]==null) throw new NullPointerException("Matrixzeile "+i+" gleich null"); try { y[i]=ScalarProduct(A[i],x); } catch (DimensionExceptione) {throw new DimensionException("Falsche Dimension in Zeile “ +i);} } return y; } DVG2 - 04
static double ScalarProduct(double [] x, double [] y) throws DimensionError { try { if (x.length != y.length) throw new DimensionError("Ungleiche Dimension der Felder im Skalarprodukt"); double sp=0.0; for (int i=0;i<x.length;i++) sp+=x[i]*y[i]; return sp; } catch (NullPointerException e) { if(x==null)throw new NullPointerException("erster Parameter null"); if(y==null)throw new NullPointerException("zweiter Parameter null"); return 0; } } DVG2 - 04
static double [] MatrixVektor(double[][]A, double[]x) throws DimensionError { int i = 0; try { double [] y = new double[A.length]; for (i=0;i<y.length;i++) y[i]=ScalarProduct(A[i],x); return y; } DVG2 - 04
catch (DimensionExceptione) { throw new DimensionException ("Falsche Dimension in Zeile "+i); } catch (NullPointerException e) { if (A==null) throw new NullPointerException("erster Parameter null"); if (x==null) throw new NullPointerException("zweiter Parameter null"); if (A[i]==null) throw new NullPointerException( "Matrixzeile "+i+" gleich null"); } return null; } DVG2 - 04