13_Exceptions - Mobile und Verteilte Systeme

Werbung
Javakurs für Anfänger
Einheit 13: Ausnahmen (Exceptions)
Lorenz Schauer
Lehrstuhl für Mobile und Verteilte Systeme
Heutige Agenda
Ausnahmen (Exceptions)
 Motivation
 Fehlerbehandlung
 Klassenhierarchie
 Checked vs. Unchecked
 Eigene Ausnahmen schreiben und werfen
Praxis:
 Übung 1
 Übung 2
Lernziele
 Einführung in die Fehlerbehandlung unter Java
 Mit Fehlern umgehen und diese behandeln können
 Eigene Ausnahmen definieren und verwenden können
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
2
Motivation
Fehler sind unvermeidbar und gehören zum Programmieren dazu.
 Programmierfehler: Sollten im Programm behoben werden (Debugging)
 Benutzer-/Laufzeitfehler: Sollten abgefangen und behandelt werden
 Bsp.: Benutzer will die Wurzel einer negativen Zahl berechnen lassen
 Erfordert Ausnahmebehandlung, damit das Programm nicht abstürzt
 Kostet viel Zeit und Ressourcen (Tests)
 Ziel: Fehlerfreies Produkt!
1. Möglichkeit: Mögliche Fehler per if-Abfragen abfangen:
// Falls kein Text eingegeben wurde:
if(tf_user.getText().equals("")){
msg.setText("Es wurde kein Nutzername
eingegeben!");
}
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
3
Exceptions als Reaktion auf Fehler
Mit if-Abfragen könnten wir theoretisch arbeiten, aber
 Sehr umständlich und aufwendig
 Es müsste jede Möglichkeit für jedes Textfeld implementiert werden!




Textfeld leer
Eingabe hat falsches Format
Eingabe ist ungültig
etc.
Daher nutzen wir Exceptions (Ausnahmen) für die Behandlung von Fehlern.
 Typisches Beispiel: Nutzer gibt eine Kommazahl, statt einer Ganzzahl ein:
Bitte geben Sie eine Ganzzahl ein:
4.6
Exception in thread "main" java.lang.NumberFormatException: For input string: "4.6"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Exceptions.FehlerhafteEingabe.main(FehlerhafteEingabe.java:12)
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
4
Behandlung von Fehlern
Solche fehlerhaften Eingaben führen dazu, dass…
 der weitere Programmablauf nicht ausgeführt wird
 und stattdessen implizit eine Excepetion ausgelöst wird.
Wenn wir solche Exceptions nicht behandeln (abfangen), dann geht es in unserem
Programm hier nicht weiter => Das Programm bricht (teilweise) ab.
Daher müssen wir auf mögliche Fehler/Ausnahmen reagieren:
 Mittels try catch können wir auftretende Exceptions abfangen:
 try{ <<Block>> }; Mit dem Schlüsselwort try wird der Versuch unternommen,
den Programmcode im einschließenden Block, wie vorgesehen, auszuführen.
 catch (Exception e){ <<Block>>}; Die catch-Anweisung nach dem try-Block
dient der Fehlerbehandlung, falls ein Fehler innerhalb des try-Blocks mit dem Typ
Exception aufgetreten ist
 Falls kein Fehler im try-Block aufgetreten ist, wird der catch-Block übersprungen!
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
5
Beispiel mit try/catch
public class FehlerhafteEingabe {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Bitte geben Sie eine Ganzzahl ein: ");
Hier kann Fehler vom Typ
int eingabe=0;
boolean show_ausgbabe=true;
NumberFormatExcpetion
auftreten!
Daher mit try umschließen
try {
eingabe = Integer.parseInt(scan.next());
Falls NumberFormatExcpetion
} catch (NumberFormatException e) {
aufgetreten ist:
System.out.println("Fehlerhafte Eingabe!");
catch-Block ausführen!
show_ausgbabe=false;
}
if(show_ausgbabe)
System.out.println("Ihre Eingabe war: "+eingabe);
}
}
Bitte geben Sie eine Ganzzahl ein:
3
Ihre Eingabe war: 3
02.02.2017
Bitte geben Sie eine Ganzzahl ein:
4.5
Fehlerhafte Eingabe!
Javakurs 13: Exceptions - Lorenz Schauer
6
Exceptions erben von Throwable
Eine Ausnahme ist letztendlich auch wieder ein Objekt
 der Klasse Exception
 oder einer Unterklasse
 und kann „ganz normal“ mit
new erzeugt werden
Die Klasse Exception selbst erbt von
der Klasse Throwable, die zahlreiche Methoden
bereitstellt
Neben Exceptions gibt es die Klasse Error:
 Ein Error bezeichnet „ernsthafte“ Problem
wie bspw.: Speicherzugriffsfehler und sollte
nicht durch die Anwendung
behandelt werden!
Quelle: http://openbook.rheinwerk-verlag.de/javainsel9/bilder/exceptionthrowableerroruml.gif
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
7
Klassenhierarchie von Exceptions
Exceptions stammen also immer von Throwable ab und können über die
Klassenhierarchie immer feiner spezifiziert sein:
 Ein kleiner Ausschnitt:
Quelle: http://openbook.rheinwerk-verlag.de/javainsel9/bilder/exceptionsuml.gif
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
8
Mit catch auf bestimmte Fehler
oder Fehlergruppen reagieren
Durch die Klassenhierarchie können wir mittels catch(Fehlertyp f) auch auf
einzelne spezielle Fehler reagieren
 Bsp.: NumberFormatException
 Unterklasse von java.lang.IllegalArgumentException
 Unterklasse von java.lang.RuntimeException
Oder eben auf ganze Fehlergruppen:
 Bsp.: IllegalArgumentException
 Reagiert auch auf:
 IllegalChannelGroupException, IllegalCharsetNameException,
IllegalFormatException, IllegalSelectorException,
IllegalThreadStateException, InvalidKeyException,
InvalidOpenTypeException, InvalidParameterException,
InvalidPathException, KeyAlreadyExistsException, …
 Mittels catch(Exception e){…} reagieren wir auf jeglichen Fehler!
 Eher vermeiden!
 Lieber Fehler im Detail behandeln
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
9
Beispiel für detaillierte
Fehlerbehandlung
public class FehlerhafteEingabe {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Bitte geben Sie eine Ganzzahl ein: ");
int eingabe=0;
boolean show_ausgbabe=true;
try {
eingabe = Integer.parseInt(scan.next());
}
catch (NumberFormatException e) {
System.out.println("Fehlerhafte Eingabe!");
show_ausgbabe=false;
}
catch (IllegalArgumentException e){
e.printStackTrace();
show_ausgbabe=false;
}
}
}
if(show_ausgbabe)
System.out.println("Ihre Eingabe war: "+eingabe);
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
Auf einen try –Block
können mehrere
catch-Blöcke folgen
Mit dem speziellsten
Fehler beginnen!
Dann in der Hierarchie
immer höher gehen!
Der erste catch-Block
der passt wird
ausgeführt!
Die anderen werden
dann übersprungen!
10
Das Schlüsselwort finally
Try-catch Konstrukte können mit dem Schlüsselwort finally ergänzt werden
 Im finally-Block wird auf jeden Fall der Code ausgeführt, selbst wenn keine
Ausnahme auftritt
 Motivation: Aufräumarbeiten o. Ä.
try {
}
int eingabe = Integer.parseInt(scan.next());
System.out.println("Ihre Eingabe war: "+eingabe);
}
catch (NumberFormatException e) {
System.out.println("Fehlerhafte Eingabe!");
}
catch (IllegalArgumentException e){
e.printStackTrace();
}
finally{
System.out.println("Programm ist zu Ende");
}
Bitte geben Sie eine Ganzzahl ein:
3
Ihre Eingabe war: 3
Programm ist zu Ende
02.02.2017
Bitte geben Sie eine Ganzzahl ein:
3.4
Fehlerhafte Eingabe!
Programm ist zu Ende
Javakurs 13: Exceptions - Lorenz Schauer
11
Überprüft oder nicht?
Ausnahmen können entweder
 nicht überprüft (unchecked) sein
 Können abgefangen werden, müssen aber nicht
 Idee: Ausnahmen, die auf einen Programmierfehler folgen, müssen nicht überprüft
werden
 Alle Arten von java.lang.RuntimeException
 überprüft (checked) sein
 Müssen abgefangen oder explizit als möglich deklariert sein
 I.d.R. Ausnahmen, die ab und zu unvermeidlich sind
 Bsp.: FileNotFoundException, IOException,…
//Fehlermeldung:
unreported exception java.io.IOException; must \
be caught or declared to be thrown
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
12
Beispiel für checked Exceptions
Beispiel: Thread.sleep(long millis) wirft eine InterruptedException
 Diese ist checked und muss behandelt werden!
Dazu 2 Möglichkeiten:
 Der Methodenaufruf sleep()
muss mit dem entspr.
try-catch Block
umgeben werden
 Die umgebene Methode muss
explizit deklarieren, dass diese
Ausnahme innerhalb
ihres Rumpfs geworfen werden
kann.
 Dann muss diese Ausnahme beim
Methodenaufruf der umgebenen
Methode abgefangen oder wieder
deklariert werden
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
13
Beispiel für checked Exceptions
public class FehlerhafteEingabe {
1. Möglichkeit:
Der Aufruf der Methode
sleep() wird mit einem
try-catch Block umzingelt,
welcher die
InterruptedExcpetion
behandelt
public static void schlafen(int dauer){
}
try {
Thread.sleep(dauer);
} catch (InterruptedException e) {
e.printStackTrace();
}
public static void main(String[] args) {
FehlerhafteEingabe.schlafen(2000);
}
}
//...
public class FehlerhafteEingabe {
public static void schlafen(int dauer) throws InterruptedException{
}
Thread.sleep(dauer);
public static void main(String[] args) {
try {
FehlerhafteEingabe.schlafen(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
//...
02.02.2017
2. Möglichkeit:
Die Methode schlafen()
deklariert explizit mit
throws die
InterruptedException
Beim Methodenaufruf von schlafen()
muss dann der Fehler abgefangen oder
die umgebene Methode deklariert den
Fehler mittels throws Statement
Javakurs 13: Exceptions - Lorenz Schauer
14
Eigene Ausnahmen definieren
Wie „ganz normale“ Klassen können wir auch eigene Ausnahmeklassen definieren
 Dabei erben wir von der entsprechenden Exception, um uns in die
Klassenhierarchie an der gewünschten Stelle einzuordnen.
 Bsp.: Wir definieren eine eigene RuntimeException (unchecked)
public class FalseSquareRootException extends RuntimeException{
public FalseSquareRootException(){
super("Kann Wurzel nicht berechnen");
}
}
Eigene Exception Klasse:
Leerer Konstruktor belegt
entsprechende Fehlermeldung
Die eigene Exception wird explizit
public static double berechneWurzel(double x){
geworfen mittels throw, wenn
if(x<0){
Wurzel auf einer negativen Zahl
throw new FalseSquareRootException();
berechnet werden soll.
}
Kann wieder abgefangen werden!
return Math.sqrt(x);
} Exception in thread "main" Exceptions.FalseSquareRootException: Kann Wurzel nicht
berechnen
at Exceptions.FehlerhafteEingabe.berechneWurzel(FehlerhafteEingabe.java:16)
at Exceptions.FehlerhafteEingabe.main(FehlerhafteEingabe.java:25)
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
15
Weitere Infos
Jede Ausnahme kennt aus der geerbten Klasse Throwable u.a. die Methoden:
 printStackTrace();
 Gibt den Typ und den Text der Fehlermeldung aus und zudem die Folge der
Methodenaufrufe bis zur ihrer Auflösung.
 Standardausgabe (auch von Eclipse)
 String getMessage();
 Gibt den String der reinen Fehlermeldung zurück
try {
result = FehlerhafteEingabe.berechneWurzel(-1);
System.out.println(result);
}
catch (FalseSquareRootException e2) {
e2.printStackTrace();
}
// oder:
catch (FalseSquareRootException e2) {
System.out.println(e2.getMessage());
}
02.02.2017
Ausgabe:
Exceptions.FalseSquareRootException:
Kann Wurzel nicht berechnen
at
Exceptions.FehlerhafteEingabe.berechneWu
rzel(FehlerhafteEingabe.java:16)
at
Exceptions.FehlerhafteEingabe.main(Fehle
rhafteEingabe.java:27)
Ausgabe:
Kann Wurzel nicht berechnen
Javakurs 13: Exceptions - Lorenz Schauer
16
Programmieraufgabe zu Exceptions
Erstellen Sie ein neues Eclipse-Projekt „Uebung13“ und schreiben Sie folgendes
Programm:
 Legen Sie eine Array-Referenz vom Typ double[] an
 Fordern Sie nun den Benutzer auf, eine Ganzzahl einzugeben, welche die Größe
des Arrays festlegen soll
 Erzeugen Sie nun das Array mit der Größe, die Sie vom Benutzer erhalten
haben.
 Welche Fehler können dabei auftreten?
 Fange Sie jeden einzelnen Fehler gesondert in einem Catch-Block ab und reagieren
Sie gesondert auf die falsche Nutzereingabe.
 Schreiben Sie auf jeden Fall „Vielen Dank für Ihre Eingabe!“ auf die Konsole am
Ende des Programms.
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
17
Programmieraufgabe zu Exceptions
Schreibe Sie ein weiteres Programm in Ihrem zuvor erstellten Projekt „Uebung13“:
 Schreiben Sie eine eigene Klasse Bruch, welche einen Dezimalbruch darstellen
soll
 Die Klasse hat die beiden Instanzvariablen:
 Double zähler
 Double nenner
 Außerdem einen Konstruktor, welcher die beiden Instanzvariablen belegt
 Und einen leeren Konstruktor
 Daneben besitzt die Klasse die Methoden
 Setter- und Getter
 double berechneBruch();
 Erzeugen Sie nun in Ihrer Main-Methode 2 Instanzen der Klasse Bruch
 Einmal mit dem leeren Konstruktor
 Und einmal mit dem Konstruktor, der Werte für Zähler und Nenner bekommt.
 Was passiert jeweils, wenn Sie die Methode berechneBruch() für Ihre beiden
Instanzen aufrufen und sich das Ergebnis auf der Konsole anzeigen lassen
wollen?
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
18
Programmieraufgabe zu Exceptions
Fortführung der Aufgabe:
 Schreiben Sie einen eigenen Fehler „DivisionByZeroException“ und geben
Sie diesem eine eindeutige Fehlermeldung mit.
 Bsp.: „Hast du in der Schule nicht gelernt, dass man nicht durch 0 teilen darf?“
 Werfen Sie den Fehler, wenn die Methode berechneBruch() durch 0 teilen
will.
 Fangen Sie den Fehler an einer geeigneten Stelle ab und geben Sie statt dem
Ergebnis die Fehlermeldung aus!
02.02.2017
Javakurs 13: Exceptions - Lorenz Schauer
19
Herunterladen