YOU ARE HERE Ausnahmen (Exceptions) Ausnahmebehandlung

Werbung
25.03.2004
YOU ARE HERE ™
Ausnahmen (Exceptions)
• Einführung
• Objektorientierte Modellierung
• Java-Sprachkonstrukte
• im Programmablauf können Ausnahmesituationen auftreten
•
•
•
•
™
•
•
•
•
•
•
•
• z.B. Division durch Null, Datei nicht vorhanden,
Übergabe eines ungültigen Parameters an eine Methode...
• allgemein: Zustand, der das Programm daran hindert, im normalen
Ablauf fortzufahren
Pakete und Zugriffskontrolle
Deklaration von Methoden, Attributen, Variablen
Ausdrücke und Anweisungen
Kontrollstrukturen
Ausnahmebehandlung
• Ziele des Entwicklers
• Erstellen eines stabilen Programms
• Trennung von fachlichem Code und Fehlerbehandlungscode
Java-Klassenbibliothek
Zeichenketten
Dateien und Streams
Datenstrukturen
Networking
Grafische Benutzungsoberflächen
Extensible Markup Language
Java-Praxiskurs
• häufig einfacher, Ausnahmesituationen eintreten zu lassen
und sie ordentlich zu behandeln,
als sie unbedingt zu vermeiden
1
Java-Praxiskurs
2
Ausnahmebehandlung: Motivation
Ausnahmebehandlung: Motivation
• Wie werden Ausnahmesituationen in Methoden signalisiert?
• Wie werden Ausnahmesituationen in Methoden signalisiert?
• in vielen Programmiersprachen über bestimmten Rückgabewert,
der als "Fehlersignal" vereinbart wird
• besonders problematisch, wenn die Methode eigentlich kein Erfolgs/Fehlersignal liefern sollte, sondern einen fachlichen Rückgabewert
public class Buch {
private int jahr; // Erscheinungsjahr
...
public boolean setJahr (int jahr) {
if (jahr > 1452) {
this.jahr = jahr;
return true; // Signal "gültiger Parameter"
}
else {
return false; // Signal "ungültiger Parameter"
}
}
public class
...
public int
if (jahr
... //
return
}
else {
return
}
}
Java-Praxiskurs
Bibliothek {
zahlDerNeuerscheinungen (int jahr) {
> 1452) {
zaehle in jahr erschienene Bücher
gefundeneAnzahl;
-1; // Signal "ungültiger Parameter"
• mögliche Rückgabewerte der Methode
• 0...n Zahl der gefundenen Bücher (bei gültigem Parameter)
• -1
Fehlersignal (bei ungültigem Parameter)
3
Java-Praxiskurs
Ausnahmebehandlung: Motivation
Ausnahmebehandlung: Motivation
• Wie werden Ausnahmesituationen erkannt?
• Probleme bei dieser Art der Ausnahmebehandlung
• Überprüfung des Rückgabewerts der Methode auf das vereinbarte
Fehlersignal
...
int anzahlNeue = uniBib.zahlDerNeuerscheinungen(suchJahr);
switch (anzahlNeue) {
case –1:
System.out.println ("Ungültiges Suchjahr.");
break;
case 0:
System.out.println ("Keine Buecher gefunden.");
break;
default:
System.out.println (anzahlNeue + " Buecher gefunden.");
System.out.println ("Buchliste anzeigen?");
...
}
...
Java-Praxiskurs
5
Lehrstuhl für Angewandte Telematik/e-Business
4
• Fehler werden auf dem gleichen Weg zurückgegeben wie reguläre
Rückgabewerte
• Rückgabewert von Methoden ist aber meistens fachlich bestimmt
und nicht gut zur Fehlersignalisierung geeignet
¾ Programmierer versuchen, Fehlersignale in Randbereichen des
fachlichen Wertebereichs unterzubringen
• Bedeutung so codierter Fehlersignale muss vereinbart werden
• wenn überhaupt, passiert das nur informell in Kommentaren
• anfällig für Missverständnisse bei der Entwicklung im Team
¾ Gefahr von falsch oder gar nicht behandelten Fehlercodes
¾ Seiteneffekte, Programmabbrüche, Apokalypse...
Java-Praxiskurs
6
1
25.03.2004
Ausnahmebehandlung: Lösung
Exceptions
• eigener Kanal für Signalisierung von Fehlern
• Fehlersignale in Java: Exceptions
• von Exception abgeleitete Klassen
¾ Entkopplung der Signale vom regulären Rückgabewert
• enthalten Methoden zur Beschreibung der Fehlersituation
• eigene Datenstrukturen für Fehlersignale
• von Java verwendete Exceptions (kleiner Auszug)
¾ differenzierte, genaue Fehlermeldungen
• ArithmeticException, ArrayIndexOutOfBoundsException,
IllegalArgumentException, NullPointerException,
NegativeArraySizeException, FileNotFoundException,
MalformedURLException, UnknownHostException u.v.m.
• formelle Deklaration möglicher Fehlersignale
¾ keine Gefahr von Missverständnissen bei der Signalvereinbarung
• erzwungene Behandlung von Fehlersignalen
• selbstdefinierte Unterklassen von Exception
¾ keine vernachlässigten oder übersehenen Fehler
• zur Signalisierung von Fehlersituationen in der eigenen Anwendung,
z.B. UngueltigesJahrException,
BuchBereitsVerliehenException, ...
• Konvention: Exceptions werden mit Suffix Exception benannt
¾ robustere Programme
Java-Praxiskurs
7
Java-Praxiskurs
Deklarieren und Werfen von Exceptions
Checked und unchecked Exceptions
• Signalisieren eines Fehlers durch "Werfen" einer Exception
• selbstdefinierte Exceptions müssen im throws-Teil des
Methodenkopfs deklariert werden
public class Bibliothek {
...
public int zahlDerNeuerscheinungen (int jahr)
throws UngueltigesJahrException {
if (jahr > 1452) {
... // in jahr erschienene Bücher zaehlen
return gefundeneAnzahl; // Wert zurückgeben
}
else {
throw new UngueltigesJahrException(); // Fehlersignal
}
}
...
}
• Deklaration der Exception(s), die die Methode im Fehlerfall
werfen kann
Java-Praxiskurs
¾ reguläres Methodenverhalten aus der Signatur ablesbar
¾ Ausnahmeverhalten der Methode aus dem throws-Teil ablesbar
• sowohl für den Programmierer als auch den Compiler
• Compiler prüft, ob deklarierte Exceptions vom aufrufenden
Programmteil abgefangen werden ("checked Exceptions")
• einige von Java generierte Exceptions müssen nicht im
throws-Teil deklariert werden
• konkret: von RuntimeException abgeleitete Exceptions
• signalisieren Laufzeitfehler, die bei umsichtiger Programmierung
eigentlich nicht auftreten dürfen
• könnten aber überall auftreten (z.B. NullPointerException)
• Abfangen wird daher vom Compiler nicht überprüft ("unchecked")
9
Java-Praxiskurs
Fangen von Exceptions: Deklaration
Fangen von Exceptions: Ablauf
• Eingrenzen des Programmteils, in dem Exceptions
geworfen werden können: try-Block
• wenn Exception auftritt, wird die Bearbeitung des tryBlocks abgebrochen und mit catch-Block fortgefahren
...
try {
int anzahlNeue = uniBib.zahlDerNeuerscheinungen(suchJahr);
if (anzahlNeue == 0)
System.out.println ("Keine Buecher gefunden.");
else {
System.out.println (anzahlNeue + " Buecher gefunden.");
System.out.println ("Buchliste anzeigen?");
...
}
}
catch (UngueltigesJahrException e) {
System.out.println ("Ungültiges Suchjahr.");
}
...
• Abfangen und Behandeln der Exception: catch-Block
Java-Praxiskurs
8
10
...
try {
int anzahlNeue = uniBib.zahlDerNeuerscheinungen(suchJahr);
if (anzahlNeue == 0)
System.out.println ("Keine Buecher gefunden.");
else {
System.out.println (anzahlNeue + " Buecher gefunden.");
System.out.println ("Buchliste anzeigen?");
...
}
}
catch (UngueltigesJahrException e) {
System.out.println ("Ungültiges Suchjahr.");
}
...
• wenn keine Exception, wird catch-Block übersprungen
11
Lehrstuhl für Angewandte Telematik/e-Business
Java-Praxiskurs
12
2
25.03.2004
Behandlungsvarianten
Fangen und andere Exception werfen
• mit catch fangen und behandeln
• z.B. um technische Fehlersignale in fachliche zu verwandeln
• häufigste Form, wie gerade gezeigt
public class Bibliothek {
private Buch[] buchBestand;
private int index = 0;
public Buch naechstesBuch () throws ListenEndeException {
try {
index++;
return buchBestand[index];
}
catch (ArrayIndexOutOfBoundsException e) {
throw new ListenEndeException();
}
}
}
• mit catch fangen und eine andere Ausnahme werfen
• z.B., um technische Fehlersignale in fachliche zu verwandeln
und sie auf höherer Ebene behandeln zu lassen
• nicht fangen, sondern "weiterfliegen" lassen
• Fehlersignal nicht selbst behandeln,
sondern von höherer Ebene behandeln lassen
• Aufrufer von naechstesBuch muss sich zwar um
ListenEndeException kümmern, muss aber nicht
wissen, dass der Buchbestand als Array implementiert ist
Java-Praxiskurs
13
Java-Praxiskurs
Exception "weiterfliegen" lassen
Exception-Behandlung durch JVM
• ...um sie von höherer Ebene behandeln zu lassen
• wenn Exception nirgends gefangen, sondern immer weiter
nach oben "durchgereicht" wird, behandelt JVM sie
public class Bibliothek {
private Buch[] buchBestand;
private int index = 0;
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 5
at Bibliothek.naechstesBuch(Bibliothek.java:8)
at Bibliothek.main(Bibliothek.java:13)
public Buch naechstesBuch ()
throws ArrayIndexOutOfBoundsException {
index++;
return buchBestand[index];
}
• Ausgabe der Exception mit Stack Trace
}
• Arrayzugriff kann ArrayIndexOutOfBoundsException
erzeugen, die aber hier nicht gefangen wird
• nicht gefangene Exceptions werden an aufrufende Methode
weitergegeben
¾ Deklaration im throws-Teil des Methodenkopfes
Java-Praxiskurs
15
•
•
•
•
Thread-Name
Name der Exception
ggf. Informationen zum Grund des Fehlers
Call Stack (Aufrufhierarchie der Methode, die Exception erzeugte)
mit Zeilennummern
¾ zielgerichtete Eingrenzung des Fehlers
Java-Praxiskurs
Werfen mehrerer Exceptions
Fangen mehrerer Exceptions
• komma-getrennte Deklaration möglicher Exceptions im Kopf
• mehrere catch-Blöcke hintereinander
public class Buch {
...
public Buch (String autor, String titel,
String verlag, int jahr)
throws KeinTitelException, UngueltigesJahrException {
this.autor = autor;
if (titel != "")
this.titel = titel;
else
throw new KeinTitelException();
this.verlag = verlag;
if (jahr > 1452)
this.jahr = jahr;
else
throw new UngueltigesJahrException();
}
...
}
Java-Praxiskurs
14
16
...
try {
neuesBuch = new Buch (neuAutoren, neuTitel, neuVerlag,
neuJahr);
}
catch (KeinTitelException e1) {
System.out.println ("Kein Titel angegeben.");
}
catch (UngueltigesJahrException e2) {
System.out.println ("Ungültiges Erscheinungsjahr.");
}
...
• wenn Exception auftritt, wird der passende catch-Block
gesucht und ausgeführt
17
Lehrstuhl für Angewandte Telematik/e-Business
Java-Praxiskurs
18
3
25.03.2004
Nachrichten in Exceptions speichern
Nachrichten aus Exceptions lesen
• Übergabe von Informationen über Fehlerursache beim
Werfen im Konstruktor der Exception
• beim Fangen wird die gerade erzeugte Referenz auf die
Exception der Variable im catch-Ausdruck zugewiesen
public class Buch {
...
public Buch (String autor, String titel,
String verlag, int jahr)
throws UngueltigeEingabeException {
this.autor = autor;
if (titel != "")
this.titel = titel;
else
throw new UngueltigeEingabeException("Kein Titel");
this.verlag = verlag;
if (jahr > 1452)
this.jahr = jahr;
else
throw new UngueltigeEingabeException("Jahr ungültig");
}
...
}
Java-Praxiskurs
19
• Zugriff auf die Methoden der Exception wie gewohnt per
Punktnotation
...
try {
neuesBuch = new Buch (neuAutoren, "", neuVerlag,
neuJahr);
}
catch (UngueltigeEingabeException e) {
System.out.println (e.getMessage()); // Ausgabe Kein Titel
}
...
• Methoden (z.B. getMessage, toString...) werden von
Oberklasse geerbt
Java-Praxiskurs
Eigene Exception-Klassen
Klassenhierarchie bei Exceptions
• Ableitung eigener Exceptions von Oberklasse Exception
• hierarchische Deklaration von Exceptions üblich
• Deklaration eines leeren Konstruktors und eines Konstruktors mit
String-Parameter, um Exceptions beim Werfen erzeugen zu können
public class EigeneException extends Exception {
public EigeneException() {
super();
}
public EigeneException(String message) {
super(message);
}
}
• z.B. Exception Å RuntimeException Å
IndexOutOfBoundsException Å
ArrayIndexOutOfBoundsException
• Vorsicht: catch-Blöcke für Ober-Exceptions fangen auch
Unter-Exceptions!
try {...}
catch (Exception e1) {
// faengt alles!
System.out.println ("Ausnahmesituation");
}
catch (ArrayIndexOutOfBoundsException e2) {
// Fehler: nicht erreichbar!
System.out.println ("Arraygrenze ueberschritten");
}
• Erinnerungen
• Bei der Ableitung werden Konstruktoren nicht mitvererbt, darum
müssen wir sie selbst deklarieren
• Wenn wir einen parametrisierten Konstruktor deklarieren, erzeugt
Java keinen impliziten leeren Konstruktor, wir müssen ihn darum
selbst deklarieren
Java-Praxiskurs
¾ catch-Reihenfolge von speziellen zu generellen Exceptions
21
Java-Praxiskurs
finally-Block
Zusammenfassung
• gelegentlich "Aufräumarbeiten" wie Schließen von Dateien
nötig, unabhängig davon, ob Exception auftrat oder nicht
• Deklaration in finally-Block nach letztem catch-Block
• wird grundsätzlich nach try- bzw. catch-Block ausgeführt
• Deklarieren und Werfen von Exceptions
• auch, wenn im try/catch-Block return oder throw o.ä. steht
try {
...
// Anweisungen
return;
}
catch (ArrayIndexOutOfBoundsException e) {
...
throw new ListenEndeException();
}
finally {
...
// Aufräumarbeiten
}
Java-Praxiskurs
20
aufrufender
Programmteil
22
typ methode (...)
throws Exceptionklasse1, Exceptionklasse2 {
...
throw new Exceptionklasse1(); // oder
throw new Exceptionklasse2(Nachricht);
...
}
• Fangen und Behandeln von Exceptions
...
try {...}
catch (Exceptionklasse1 e) {...}
catch (Exceptionklasse2 e) {...}
finally {...}
...
• Ableiten eigener Exceptions von Oberklasse Exception
23
Lehrstuhl für Angewandte Telematik/e-Business
Java-Praxiskurs
24
4
25.03.2004
YOU ARE HERE ™
Java-Klassenbibliothek
• Einführung
• Objektorientierte Modellierung
• Java-Sprachkonstrukte
™ Java-Klassenbibliothek
• Zeichenketten
• Dateien und Streams
• Datenstrukturen
• Networking
• Grafische Benutzungsoberflächen
• Extensible Markup Language
• Sprachumfang von Java entspricht im Wesentlichen
dem von anderen Sprachen
Java-Praxiskurs
• Mächtigkeit von Java bedingt durch umfangreiche
Klassenbibliothek
• Vorteil: im Wesentlichen plattformübergreifend verfügbar
• Bibliothek in Pakete gegliedert
• Pakete wie selbstdefinierte Pakete verwendbar
25
Überblick (Auszug)
•
•
•
•
•
•
•
•
•
•
•
java.applet
java.awt
java.beans
java.io
java.lang
java.net
java.rmi
java.security
java.sql
java.util
javax.swing
Java-Praxiskurs
26
Java API Specification
Applet-Programmierung
GUI-Programmierung mit AWT
JavaBeans™-Entwicklung
Ein-/Ausgabe-Operationen, Datenströme
fundamentale Klassen (z.B. String)
Netzwerkfunktionen
Remote Method Invocation
Zertifikate, Kryptographie
Datenbank-Funktionen
Klassen für Datenstrukturen
GUI-Programmierung mit Swing
• und viele mehr (XML, CORBA, Namensdienste, Sound...)
Java-Praxiskurs
27
Java-Praxiskurs
YOU ARE HERE ™
Klasse String
• Einführung
• Objektorientierte Modellierung
• Java-Sprachkonstrukte
• Java-Klassenbibliothek
™ Zeichenketten
• Dateien und Streams
• Datenstrukturen
• Networking
• Grafische Benutzungsoberflächen
• Extensible Markup Language
• Zeichenketten sind String-Objekte mit Besonderheiten:
Java-Praxiskurs
28
• Erzeugen von String-Objekten aus String-Literalen
String a = "Hello", b = "World";
• Verknüpfen von Strings mit dem Operator +
String c = a + " " + b;
• Methoden funktionieren auch mit Literalen
int laenge = "Literal".length(); // 7
• ansonsten verhalten Strings sich wie Referenztypen
• == vergleicht Referenzen auf String-Objekte, nicht String-Inhalte
• aber: String-Objekte sind unveränderbar ("immutable")
• Zuweisung eines Literals oder Ausdrucks erzeugt neuen String
• Methoden von String verändern den Objekt-Inhalt nicht,
sondern geben ein neues String-Objekt zurück
¾ Vermeidung von Seiteneffekten
29
Lehrstuhl für Angewandte Telematik/e-Business
Java-Praxiskurs
30
5
25.03.2004
String-Konstruktoren
Methoden für String-Vergleiche
• Leerstring
• Referenzvergleich
• String s = new String(); // ""
• boolean result = (s == t);
• true, wenn s und t die gleiche String-Referenz enthalten
• String aus char-Array
• inhaltlicher Vergleich
• char[] c = {'J', 'a', 'v', 'a'};
String s = new String(c); // "Java"
• boolean result = s.equals(t);
• true bei Übereinstimmung aller Zeichen
• boolean result = s.equalsIgnoreCase(t);
• String aus anderem String (Kopie)
• wie oben, ohne Berücksichtigung von Groß-/Kleinschreibung
• String s = "Java";
String sKopie = new String(s); // "Java"
• lexikographischer Vergleich ("wie im Telefonbuch")
• int result = s.compareTo(t);
int result = s.compareToIgnoreCase(t);
• result < 0:
s lexikographisch vor t
• result == 0:
s identisch mit t
• result > 0:
s lexikographisch hinter t
• weitere Konstruktoren für spezielle Anwendungsfälle
(Æ Java API Specification)
Java-Praxiskurs
31
Java-Praxiskurs
Methoden für Teilstring-Vergleiche
Methoden zur String-Manipulation
• Beginn mit bestimmter Zeichenkette?
• ein Zeichen aus String herauskopieren
• char charAt (int index)
• boolean startsWith (String prefix)
• Teilstring aus String herauskopieren
• Ende mit bestimmter Zeichenkette?
• String substring(int beginIndex, int endIndex)
• boolean endsWith (String suffix)
• Zeichen in String ersetzen
• Position des ersten Auftretens eines bestimmten Zeichens
• String replace(char oldChar, char newChar)
• int indexOf (char ch)
• Teilstring in String ersetzen (mit Regular Expressions)
• Position des ersten Auftretens eines bestimmten Strings
• String replaceAll(String regex, String replacemnt)
• int indexOf (String s)
• String in Groß- bzw. Kleinschreibung umwandeln
• Position des letzten Auftretens eines bestimmten Zeichens
• String toLowerCase() bzw. String toUpperCase()
• int lastIndexOf (char ch)
• Leerzeichen am Anfang und Ende entfernen
• Position des letzten Auftretens eines bestimmten Zeichens
• String trim()
• Beachte: Methoden ändern nicht den Inhalt ihres StringObjekts, sondern geben neues String-Objekt zurück!
• int lastIndexOf (String s)
• oft existieren noch überladene Varianten dieser Methoden!
Java-Praxiskurs
33
Java-Praxiskurs
primitive Typen in Strings umwandeln
Strings in primitive Typen umwandeln
• valueOf-Methode (für viele Argumenttypen überladen)
• in Wahrheitswert:
•
•
•
•
•
•
•
static
static
static
static
static
static
static
String
String
String
String
String
String
String
valueOf(boolean b)
valueOf(char c)
valueOf(char[] data)
valueOf(double d)
valueOf(float f)
valueOf(int i)
valueOf(long l)
34
• keine explizite Umwandlungsmethode; möglicher Ausdruck:
• boolean bo = s.equals("true");
• in Zahlenwert:
• parse...-Klassenmethoden von Zahlenklassen:
• byte by = Byte.parseByte(s);
• short sh = Short.parseShort(s);
• int i = Integer.parseInt(s);
• long l = Long.parseLong(s);
• float f = Float.parseFloat(s);
• double d = Double.parseDouble(s);
• werfen NumberFormatException, wenn Umwandlung aufgrund
von Formatfehlern unmöglich (z.B. "3.5" nicht in int wandelbar)
• Klassenmethoden!
¾ Aufruf mit String.valueOf(...)
String s;
int i = 10;
s = String.valueOf(i); // "10"
Java-Praxiskurs
32
35
Lehrstuhl für Angewandte Telematik/e-Business
Java-Praxiskurs
36
6
25.03.2004
String vs. StringBuffer
Zusammenfassung
• String-Objekte sind unveränderbar
• Java-Klassenbibliothek
• Manipulationen werden nicht auf dem ursprünglichen String
ausgeführt, sondern auf einem dafür neu erzeugten String-Objekt
• kann Performance beeinträchtigen, wenn sehr viele Änderungen
eines Strings notwendig sind
• mächtiger Funktionsumfang für viele Anwendungsbereiche
• Dokumentation: Java API Specification von Sun
• String
• Abhilfe: StringBuffer-Objekte mit veränderbarem Inhalt
• StringBuffer speichert eine Zeichenkette, die auch nachträglich
geändert werden kann (ohne ein neues Objekt erzeugen zu müssen)
• Vorteil: in bestimmten Anwendungen Performance-Gewinn möglich
• Nachteil: Seiteneffekte wie bei anderen Referenztypen möglich
• Erzeugen: StringBuffer sb = new StringBuffer("Hi");
• Anfügen: sb.append(" there"); // sb jetzt "Hi there"
• in normalen String kopieren: String s = sb.toString();
• Empfehlung: Strings in der Regel komfortabler
Java-Praxiskurs
37
Lehrstuhl für Angewandte Telematik/e-Business
•
•
•
•
•
•
Referenztyp mit einigen Besonderheiten
unveränderbar – Methoden erzeugen neue Objekte
verschiedene Konstruktoren
Methoden für String- und Teilstring-Vergleiche
Methoden zur String-Manipulation
Typumwandlung von und zu Strings
• StringBuffer
• enthält veränderliche Strings
• für performancekritische Anwendungen mit vielen Manipulationen
Java-Praxiskurs
38
7
Herunterladen