Java Exceptions Handling: Fehler- und Ausnahmenbehandlung in Java
Java Exceptions Handling umfasst den richtigen Umgang mit Ausnahmen und Fehlern.
Wie geht das?
Und braucht man so etwas wirklich?
Vielleicht sagst du jetzt:
„Brauch ich nicht. Ich mache niemals Fehler.“
Doch…
Bei der Java Fehlerbehandlung geht es nicht ausschließlich nur um deine Programmierfehler.
Es geht auch um falsche Nutzereingaben, Hardware- und Ablauffehler.
Und deshalb – Lass uns in diesem Beitrag einmal anschauen:
- Welche Fehler in einem Java Programm auftreten können.
- Wie du dir eine Fehlerbehandlung in Java theoretisch vorstellen kannst.
- Und wie die praktische Umsetzung aussehen würde.
Inhalt
In einem Java Programm können alle möglichen Fehler auftreten
Hier ein paar Beispiele:
public class JavaFehlerBehandlung {
public static void main(String[] args) {
int[] zahlen = new int[1];//neues Integer-Array mit einm Fach
zahlen[0] = 1; //Belegung des erstes Faches mit der Zahl 1
//For-Schleife durchläuft die ersten 10-Fächer des Arrays
for (int i = 0; i <= 10; i++) {
System.out.println("Fach " + i + ": " + zahlen[i]);
}
}
}
In der main-Methode wird ein neues Array angelegt.
Dieses Array hat eine Länge von 1.
Somit bietet es Platz für eine einzige Zahl.
Und zwar im Fach Null.
Okay – Also habe ich, in das Fach Null den Wert 1 platziert.
Soweit ist alles gut.
Doch dann….
Habe ich eine For-Schleife angelegt, welche die ersten zehn Fächer des Arrays durchlaufen soll.
Und im Rumpf der Schleife sollen mir dann die Werte der einzelnen Fächer auf der Konsole ausgegeben werden.
Am besten ist es, du schreibst den Code ab und probierst es selbst einmal aus.
Klick dann auf „RUN“ und schau nach, was passiert.
Und?
Es kommt zur Fehlermeldung.
Warum?
Einfach aus dem Grund, da die For-Schleife 10 Fächer durchlaufen soll.
Das Array hat aber nur ein Fach.
Als Fehlermeldung steht dann:
„Exception in thread „main“ java.lang.ArrayIndexOutOfBoundsException“
Oder ein zweites Beispiel:
Beispiel 2: Die Division durch Null.
public class JavaFehlerBehandlung {
public static void main(String[] args) {
int dividend = 10;
int divisor = 0;
System.out.println(dividend / divisor);
}
}
Probiere auch diesen Code einmal selbst aus.
Und? Wieder erscheint eine Fehlermeldung.
Es können aber noch mehr Fehler auftreten.
Zum Beispiel durch Nutzereingaben:
Angenommen du möchtest in deinem Programm das Alter des Nutzers prüfen.
Dazu forderst du den Nutzer auf, sein Alter anzugeben.
Locker wie er ist – schreibt dieser statt des Alters, seinen Namen in das Feld.
Und bei diesem eingegebenen Textwert (Namen), kann dein Programm kein Alter finden.
Also – Fehler.
Oder dein Programm speichert bestimmte Daten lokal auf der Festplatte ab.
Und beim Neustart will das Programm jetzt die alten Daten anfordern.
Jetzt will es Laden….
Und auf einmal ist die Datei nicht mehr da.
Was dann?
Bis jetzt ist es so, dass durch die Fehlermeldungen das Java Programm abstürzen würde.
Es kommt nämlich nicht nur zu einer Fehlermeldung auf der Konsole.
Nein – das Programm wird beendet.
So wie hier.
public class JavaFehlerBehandlung {
public static void main(String[] args) {
int dividend = 10;
int divisor = 0;
System.out.println(dividend / divisor);
System.out.println("Test");// Diese Ausgabe erscheint nicht.
}
}
Die zweite Bildschirmausgabe enthält keinen Fehler.
Ohne die Divisionsanweisung sollte somit der zweite Teil des Programmes ausgeführt werden.
Das klappt aber nicht.
Sobald das Programm irgendeinen Fehler erkennt – kommt es zur Meldung und zum Programmabsturz.
Also was kannst du machen?
Java bietet dir für die Fehlerbehandlung eine spezielle Klasse an.
Und diese Klasse nennt sich Throwable.
Wie sämtliche andere Klassen, findest du die Dokumentation in den Java API Docs.
Ganz oben siehst du die Importanweisung und die Vererbungsstruktur.
Wie sämtliche anderen Java Klassen erbt auch diese Klasse von der Klasse Objekt.
Du siehst auch, dass diese Klasse zwei Kindklassen besitzt.
- Zum einen die Klasse Error bzw. Fehler.
- Und zum anderen die Klasse Exceptions bzw. Ausnahme.
Worin liegt jetzt der Unterschied zwischen einem Fehler und einer Ausnahme?
Ein Fehler ist immer etwas Generelles.
Das würde bedeuten, dass dies immer auftritt.
Eine Ausnahme tritt nur in bestimmten Fällen auf.
Wenn du dir die eingangs erwähnten Beispiele mal so anschaust- handelt es sich um Fehler oder um Ausnahmen?
Falsche Benutzereingabe führt zum Programmabsturz:
Dies ist eine Ausnahme – denn die richtige Eingabe führt zu einem weiterhin stabilen Programmablauf.
Wenn die Benutzereingabe ein Fehler wäre – dann würde jede Eingabe zum Absturz führen.
Bei allen anderen Beispielen ist es genauso:
Nicht die Division führt generell zum Programmabsturz.
Nein – Nur die Division durch Null führt zum Absturz.
Also wird auch hier eine Ausnahme behandelt.
Wir sprechen also bei sämtlichen auftretenden Beispielen, von Ausnahmen anstatt von Fehlern.
Und deshalb solltest du das Wort „Fehlerbehandlung“ durch das Wort „Ausnahmebehandlung“ ersetzen.
Schauen wir uns die Kindklasse Exceptions genauer an
Klicke dazu einmal auf die Unterklasse in den API Docs und du wirst direkt zur Dokumentation geleitet.
Oben siehst du wieder die Klassenhierarchien.
Die Klasse Exceptions erbt von Throwable.
Und diese wiederum erbt von Objekt.
Direkt darunter, siehst du die einzelnen Kindklassen von Exceptions.
Ne ganze Menge, oder?
Es gibt eben jede Menge verschiedene Ausnahmen.
Und all diese werden entsprechend separat behandelt.
Aber es geht noch weiter.
Denn auch diese einzelnen Kindklassen, haben wiederum speziellere Kindklassen.
Warum so detailliert?
Und warum bietet Java nicht ganz einfache Standards an?
Schließlich ist doch die ganze Ausnahmebehandlung nur so eine Art Beiwerk in einem Programm.
Die Ausnahmebehandlung ist die Aufgabe des Entwicklers und nicht Aufgabe von Java
Stell dir vor – Java würde die Ausnahmebehandlung „Division durch Null“ in der Standardbibliothek anbieten.
Und du hättest eine grafische Oberfläche in einem Programm.
Dein Nutzer müsste zwei Zahlen in einem Feld eingeben und diese würden dann mit einander dividiert werden.
Eben eine Art Taschenrechner.
Jetzt kommt es zur Ausnahme.
Also würde in einer grafischen Oberfläche ein Pop-Up-Fenster aufblinken.
Und der Nutzer würde auf seine Falscheingabe hingewiesen werden.
Diese grafische Oberfläche müsste aber vom Design, von den Farben und vom Logo zum restlichen Programm passen.
Es ist ganz logisch, dass Java dies nicht standardisiert für sämtliche Programme bereitstellen könnte.
Du als Java Programmierer musst dich eben schon selbst, um deine Exceptions kümmern.
Und das machen wir jetzt auch.
Java Exceptions Handling am klassischen Beispiel.
Nehmen wir den Klassiker – die Division durch Null.
public class JavaFehlerBehandlung {
public static void main(String[] args) {
int dividend = 10;
int divisor = 0;
System.out.println(dividend / divisor);
}
}
Verfeinern wir doch das Ganze.
Und legen richtige Benutzereingaben mit dem Scanner an.
import java.util.Scanner;//Importanweisung für den Scanner
public class JavaFehlerBehandlung {
public static void main(String[] args) {
Scanner eingabe = new Scanner(System.in);//neues Scannerobjekt
System.out.println("Gib eine Zahl für den Dividenden");
int dividend = eingabe.nextInt();//Dividend wird gespeichert
System.out.println("Und jetzt gib den Divisor ein");
int divisor = eingabe.nextInt();//Divsior wird gespeichert
System.out.println(dividend / divisor);
}
}
Wenn du jetzt auf „RUN“ klickst – läuft die Show.
Und zwar nur solange – bis du auf die Idee kommst, als Divisor die 0 einzugeben.
Dann endet das Ganze in einem Programmabsturz.
Was kannst du jetzt tun?
Eine Alternative wäre die Null abzufangen.
Und zwar mit einem if und else Block.
So etwas haben wir in den Übungen auch regelmäßig gemacht.
Das würde dann so aussehen:
import java.util.Scanner;//Importanweisung für den Scanner
public class JavaFehlerBehandlung {
public static void main(String[] args) {
Scanner eingabe = new Scanner(System.in);//neues Scannerobjekt
System.out.println("Gib eine Zahl für den Dividenden");
int dividend = eingabe.nextInt();//Dividend wird gespeichert
System.out.println("Und jetzt gib den Divisor ein");
int divisor = eingabe.nextInt();//Divsior wird gespeichert
if (divisor !=0){
System.out.println(dividend / divisor);
}
else {
System.out.println("Eingabe ungültig!");
}
}
}
Und jetzt funktioniert es solange bis ein User auf die Idee kommt, keine Zahlen einzugeben.
Statt der 5 gibt dieser Nutzer dann den Text „Fünf“ ein.
Was dann? – Klar nächster Fehler.
Du könntest jetzt sämtliche if / else Kontrollstrukturen aufstellen und versuchen jede Ausnahme abzufangen.
Doch es geht natürlich einfacher.
Und zwar mit Exceptions.
Und wie?
Beim Exception Handling benötigst du zwei Codeblöcke.
Der erste Codeblock beginnt mit dem Keywort try.
Hier platzierst du deine Anweisungen, welche ausgeführt werden sollen.
Der zweite Codeblock beginnt mit dem Keywort catch.
In diesem platzierst du all das, was passieren soll – falls eine Ausnahme auftritt.
Außerdem musst nach dem Keywort catch eine Variable vom Datentyp Exception anlegen.
In dieser wird dann die Ausnahme gespeichert.
Und du kannst diese auch später auswerten
import java.util.Scanner;
public class JavaFehlerBehandlung {
public static void main(String[] args) {
Scanner eingabe = new Scanner(System.in);
System.out.println("Gib eine Zahl für den Dividenden");
int dividend = eingabe.nextInt();
System.out.println("Und jetzt gib den Divisor ein");
int divisor = eingabe.nextInt();
try {
System.out.println(dividend / divisor);
} catch (Exception e) {
System.out.println("Falsche Eingabe!");
}
}
}
So fertig.
Wenn du jetzt die 0 als Divisor übergeben würdest, würde das Programm nicht abstürzen.
Stattdessen kommt es zur Fehlermeldung bzw. Ausnahmebehandlung.
Doch probiere mal einen Textwert einzugeben.
Und klicke dann auf „RUN“.
Na was passiert?
Wieder ein Fehler.
Denn die Anweisungen int dividend = eingabe.nextInt();
oder int divisor = eingabe.nextInt();
wurden noch nicht abgefangen.
Bis jetzt wird nur die Ausnahme bei der Division behandelt.
Die Ausnahme bei der Eingabe steht nicht im try-Block und wird somit nicht behandelt.
Also was wäre noch zu tun?
Klar den try-Block einfach weiter oben ansetzen.
import java.util.Scanner;
public class JavaFehlerBehandlung {
public static void main(String[] args) {
Scanner eingabe = new Scanner(System.in);
try { // Beginn try-Block
System.out.println("Gib eine Zahl für den Dividenden");
int dividend = eingabe.nextInt();
System.out.println("Und jetzt gib den Divisor ein");
int divisor = eingabe.nextInt();
System.out.println(dividend / divisor);
} // Ende try-Block
catch (Exception e) {
System.out.println("Falsche Eingabe!");
}
}
}
Jetzt werden sämtliche Ausnahme bei der Eingabe und Verarbeitung abgefangen.
Klicke auf „RUN“!
Und läuft, oder?
Zusammenfassung:
- In Java können Fehler und Ausnahmen behandelt werden.
- Von einem Fehler spricht man, wenn etwas generell und immer auftritt.
- Von einer Ausnahme spricht man, wenn das Programm eigentlich stabil läuft und es nur, beim Auftreten einer bestimmten Ursache, zum Abbruch kommt. Zum Beispiel bei einer Falscheingabe.
- Programmfehler und auch die Ausnahme führen immer zum Programmabsturz.
- Die Ausnahmen oder Exceptions kannst du aber behandeln.
Dazu musst du einen try-Block einsetzen.
Und in diesen Block platzierst du alle Anweisungen, welche ausgeführt und überprüft werden sollen.
Also all das – was passieren soll, falls keine Ausnahme auftritt. - Im zweiten Block, den catch Block, platzierst du all das – was passieren soll – falls es zur Ausnahme kommt.
Außerdem musst du im catch Block ein Objekt vom Datentyp Exception anlegen, welches die Ausnahme entgegen nimmt. - Somit kannst du in Java Exceptions abfangen und behandeln.