Wiederholung: Ausnahmebehandlung Wdh.: Exceptions werfen und

Werbung
26.03.2004
Wiederholung: Ausnahmebehandlung
Wdh.: Exceptions werfen und fangen
• Problem in vielen Programmiersprachen
• Deklarieren und Werfen von Exceptions
• Fehler werden auf dem gleichen Weg zurückgegeben wie reguläre
Rückgabewerte
¾ Programmierer versuchen, Fehlersignale in Randbereichen des
fachlichen Wertebereichs unterzubringen
• Bedeutung so codierter Fehlersignale muss informell vereinbart
werden
¾ Gefahr: falsch interpretierte oder nicht behandelte Fehlercodes
typ methode (...)
throws Exceptionklasse1, Exceptionklasse2 {
...
throw new Exceptionklasse1(); // oder
throw new Exceptionklasse2(Nachricht);
...
}
• Fangen und Behandeln von Exceptions
• Lösung: Exceptions
•
•
•
•
...
try {...}
catch (Exceptionklasse1 e) {...}
catch (Exceptionklasse2 e) {...}
finally {...}
...
eigener Kanal für Signalisierung von Fehlern
eigene Datenstrukturen für Fehlersignale
formelle Deklaration möglicher Fehlersignale
erzwungene Behandlung von Fehlersignalen
Java-Einführungskurs
1
Java-Einführungskurs
2
Wiederholung: Behandlungsvarianten
Wiederholung: Eigene Exceptions
• Exception mit catch fangen und behandeln
• Ableitung eigener Exceptions von Oberklasse Exception
• Deklaration eines leeren Konstruktors und eines Konstruktors mit
String-Parameter, um Exceptions beim Werfen erzeugen zu können
• Blaupause für Implementierung eigener Exceptions:
• Fehler dort behandeln, wo er signalisiert worden ist
• Exception mit catch fangen und andere Exception werfen
public class EigeneException extends Exception {
public EigeneException() {
super();
}
public EigeneException(String message) {
super(message);
}
}
• z.B., um technische Fehlersignale in fachliche zu verwandeln
und sie auf höherer Ebene behandeln zu lassen
• Exception nicht fangen, sondern "weiterfliegen" lassen
• Fehlersignal nicht selbst behandeln,
sondern von höherer Ebene behandeln lassen
• Erinnerungen
• Bei der Ableitung werden Oberklassen-Konstruktoren nicht vererbt
• Wenn wir einen parametrisierten Konstruktor deklarieren, erzeugt
Java keinen impliziten leeren Konstruktor, wir müssen ihn darum
selbst deklarieren
Java-Einführungskurs
3
Wiederholung: JavaJava-Klassenbibliothek
•
•
•
•
•
•
•
•
•
•
•
java.applet
java.awt
java.beans
java.io
java.lang
java.net
java.rmi
java.security
java.sql
java.util
javax.swing
4
Wiederholung: Strings
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
Datenstrukturen
GUI-Programmierung mit Swing
• Referenztypen mit einigen Besonderheiten
• direkte Zuweisung von Literalen: String s = "Hello";
• Konkatenation mit Operator: String t = s + "World";
• Methoden von Literalen aufrufbar: "HelloWorld".equals(t)
• unveränderbar: Verknüpfungen/Methoden erzeugen neue Objekte
•
•
•
•
verschiedene Konstruktoren zur String-Erzeugung
Methoden für String- und Teilstring-Vergleiche
Methoden zur String-Manipulation
Typumwandlung von und zu Strings
• String
double
• double
String
• und viele mehr (XML, CORBA, Namensdienste, Sound...)
Java-Einführungskurs
Java-Einführungskurs
5
Lehrstuhl für Angewandte Telematik/e-Business
Java-Einführungskurs
s
d
d
s
=
=
=
=
"2.71828";
Double.parseDouble(s); // 2.71828
3.14159;
String.valueOf(d); // "3.14159"
6
1
26.03.2004
Ü4.1 Null Peilung
Ü4.2 Ausnahmezustand
™ Die Klasse java.lang.NullPointerException
beschreibt den Versuch, auf eine Referenzvariable
zuzugreifen, in der statt eines Objektes die Referenz null
abgelegt ist. Welche Informationen können Sie ohne
Kenntnis des genauen Programmcodes aus folgender
Programmausgabe ziehen?
• Das folgende Programm soll eine double-Fließkommazahl von der
Tastatur einlesen, sie in einen String umwandeln und diesen wieder
ausgeben. Falls die Umwandlung nicht möglich ist (weil der Benutzer
etwas eingegeben hat, das sich nicht nach double umwandeln lässt,
z.B. "schrott"), soll das Programm den Benutzer so lange zur
Eingabe auffordern, bis er eine gültige double-Zahl eingibt.
• In der main-Methode wird die Methode readDouble aufgerufen. Diese
nimmt in der Anweisung s = in.readLine(); eine Tastatureingabe
(d.h. einen String) entgegen und wandelt ihn in der Anweisung
d = Double.parseDouble(s); in eine double-Zahl um.
Um diese Anweisungen herum ist eine do-while-Schleife angedeutet,
die dafür sorgen soll, dass die Eingabe so oft angefordert wird, bis die
Typumwandlung erfolgreich war.
java.lang.NullPointerException
at Peilung.problem(Peilung.java:6)
at Peilung.main(Peilung.java:10)
• in Zeile 10 der Methode main von Peilung (gespeichert in
Peilung.java) wurde die Methode problem aufgerufen
• in Zeile 6 der Methode problem von Peilung wurde eine
NullPointerException geworfen
¾ dort wurde versucht, auf ein Objekt zuzugreifen, obwohl in
der betreffenden Variable null statt der Referenz stand
Java-Einführungskurs
• Die Fehlerbehandlung für den Fall, dass die Typumwandlung nicht
erfolgreich war, soll von Ihnen in den folgenden Aufgabenteilen
ausprogrammiert werden.
7
Java-Einführungskurs
Ü4.2 Ausnahmezustand
Ü4.2.1 "unreported
"unreported exception"
exception"
import java.io.*;
public class EingabeValidierung {
// Eingabekanal von der Tastatur
private static BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
™ 1. Beim Kompilierungsversuch erhalten wir die Meldung
EingabeValidierung.java:17: unreported exception
java.io.IOException; must be caught or declared to be
thrown
• Sie weist darauf hin, dass die Methode readLine (der
Klasse BufferedReader) eine IOException werfen
kann, die jedoch noch nirgends von uns gefangen wird.
• Die Methode parseDouble der Klasse Double kann eine
NumberFormatException werfen, die wir auch noch nicht
abgefangen haben – darüber beschwert der Compiler sich
jedoch nicht.
• Welcher Unterschied zwischen java.io.IOException
und java.lang.NumberFormatException ist für die
Compiler-Fehlermeldung verantwortlich?
public static double readDouble() {
String s;
double d = 0.0;
boolean korrekt = true;
}
}
// String-Eingabe und Typumwandlung - zu vervollständigen:
do {
System.out.print("Bitte double-Zahl eingeben: ");
s = in.readLine();
// Tastatureingabe entgegennehmen
d = Double.parseDouble(s); // Eingabestring in double wandeln
} while (!korrekt);
return d;
public static void main (String[] args) {
double eingabe = readDouble();
System.out.println("Eingabe: " + eingabe);
}
Java-Einführungskurs
9
Java-Einführungskurs
Ü4.2.1 "unreported
"unreported exception"
exception"
Ü4.2.2 trytry-catchcatch-Struktur
• Oberklassen von IOException
™ 2. Ergänzen Sie den Inhalt der do-while-Schleife um eine
try-catch-Struktur, die beide Arten von Exceptions
abfängt.
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.io.IOException
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IllegalArgumentException
java.lang.NumberFormatException
• RuntimeExceptions sind "unchecked"
können prinzipiell überall auftreten
nicht sinnvoll, überall zu prüfen, ob sie abgefangen werden
Compiler erzwingt Behandlung nicht
i.d.R. Weitergabe an die JVM
Java-Einführungskurs
10
...
do {
System.out.print("Bitte double-Zahl eingeben: ");
try {
korrekt = true;
s = in.readLine();
d = Double.parseDouble(s);
}
catch (IOException e) { // nur vorerst leer
}
catch (NumberFormatException e) {
System.out.println("Keine zulaessige double-Zahl!");
korrekt = false;
}
} while (!korrekt);
...
• Oberklassen von NumberFormatException
•
•
¾
¾
8
11
Lehrstuhl für Angewandte Telematik/e-Business
Java-Einführungskurs
12
2
26.03.2004
Ü4.2.3 Reihenfolge der catchcatch-Blöcke
Ü4.2.4 leere catchcatch-Blöcke
™ 3. Ist die Reihenfolge der catch-Blöcke in diesem Beispiel
von Bedeutung? Warum?
™ 4. Obwohl die IOException in unserem Beispiel kaum
auftreten kann, ist ein leerer catch-Block extrem schlechter
Programmierstil. Warum?
catch (IOException e) { // nur vorerst leer
}
catch (NumberFormatException e) {
System.out.println("Keine zulaessige double-Zahl!");
korrekt = false;
}
Reihenfolge ist nicht von Bedeutung, da IOException und
NumberFormatException keine Vererbungsbeziehung
haben.
Keiner der beiden catch-Blöcke kann also Exceptions
fangen, die für den anderen bestimmt sind.
Java-Einführungskurs
13
catch (IOException e) { // nur vorerst leer
}
catch (NumberFormatException e) {
System.out.println("Keine zulaessige double-Zahl!");
korrekt = false;
}
...
Die Exception wird zwar gefangen, aber in keiner Weise
verarbeitet – aus dem leeren catch-Block wird direkt zum
regulären Programmcode weitergesprungen.
"Verschlucken" von Exceptions ist aber kaum sinnvoll, da
der Fehler damit ignoriert wird.
Java-Einführungskurs
Ü4.2.5 ExceptionException-Behandlung
Ü4.2.6 ExceptionException-Klassendeklaration
™ 5. Welche drei Möglichkeiten haben wir, auf die
IOException in diesem Beispiel (bzw. im Allgemeinen auf
jede Exception) zu reagieren?
™ 6. Erweitern Sie die Methode readDouble so, dass sie im
Fall einer IOException eine neue, von Ihnen deklarierte
InputException wirft.
Deklarieren Sie dazu InputException als Unterklasse
von Exception.
• Exception mit catch fangen und behandeln
• Fehler dort behandeln, wo er signalisiert worden ist
public class InputException extends Exception {
public InputException() {
super();
}
• Exception mit catch fangen und andere Exception werfen
• z.B., um technische Fehlersignale in fachliche zu verwandeln
und sie auf höherer Ebene behandeln zu lassen
public InputException(String message) {
super(message);
• Exception nicht fangen (kein catch),
sondern "weiterfliegen" lassen
}
}
• Fehlersignal nicht selbst behandeln,
sondern von höherer Ebene behandeln lassen
Java-Einführungskurs
15
Ü4.2.6 Werfen einer eigenen Exception
}
Java-Einführungskurs
16
Ü4.2.7 Behandeln eigener Exceptions
public static double readDouble() throws InputException {
String s;
double d = 0.0;
boolean korrekt = true;
do {
System.out.print("Bitte double-Zahl eingeben: ");
try {
korrekt = true;
s = in.readLine();
d = Double.parseDouble(s);
}
catch (IOException e) {
throw new InputException("Fehler in Tastatureingabe");
}
catch (NumberFormatException e) {
System.out.println("Keine zulaessige double-Zahl!");
korrekt = false;
}
} while (!korrekt);
return d;
Java-Einführungskurs
14
17
Lehrstuhl für Angewandte Telematik/e-Business
™ 7. Der Compiler weist darauf hin, dass die von readDouble
geworfene InputException in main noch nicht behandelt
wird. Überlegen Sie, welche beiden Möglichkeiten Sie dafür
haben, und implementieren Sie eine von beiden in main.
• Alternative 1: Fangen und behandeln
public static void main (String[] args) {
try {
double eingabe = readDouble();
System.out.println("Eingabe: " + eingabe);
}
catch (InputException e) {
System.out.println (e.getMessage());
}
}
Bitte double-Zahl eingeben: Fehler in Tastatureingabe
Java-Einführungskurs
18
3
26.03.2004
Ü4.2.7 Behandeln eigener Exceptions
Ü4.3 StringString-Vergleiche
• Alternative 2: "Weiterfliegen" lassen (d.h. zum aufrufenden
Programmteil durchreichen)
String s1 = "Test";
String s2 = s1;
String s3 = "Te";
String s4 = "st";
String s5 = s3 + s4;
™ Welchen Wert haben die folgenden Ausdrücke?
public static void main (String[] args)
throws InputException {
double eingabe = readDouble();
System.out.println("Eingabe: " + eingabe);
}
Da dies die main-Methode ist, ist der aufrufende
Programmteil die JVM, wo die Exception einfach
ausgegeben wird:
s1 == s2
s1.equals(s2)
s1.compareTo(s2)
true: gleiche Referenz
true: gleiche Referenz
Æ gleiche Zeichenketten
0: gleiche Referenz
Æ gleiche Zeichenketten
s3 == s4
s3.equals(s4)
s3.compareTo(s4)
false: verschiedene
Referenzen
false: verschiedene
Zeichenketten
-31: 'T' liegt in ASCII
31 Zeichen vor 's'
s1 == s5
s1.equals(s5)
s1.compareTo(s5)
false: verschiedene
Referenzen
true: gleiche
Zeichenketten
0: gleiche Zeichenketten
('T': ASCII 84; 's': ASCII 115)
Bitte double-Zahl eingeben: Exception in thread "main"
InputException: Fehler in Tastatureingabe
at EingabeValidierung.readDouble(EingabeValidierung.java:19)
at EingabeValidierung.main(EingabeValidierung.java:33)
Java-Einführungskurs
19
Java-Einführungskurs
20
Ü4.4 Referenzen in main
Ü4.4 StringString-Parameter
public static void main(String[] args) {
String sAussen = "Hello";
String tAussen = "klein";
methode(sAussen, tAussen);
System.out.println(sAussen);
System.out.println(tAussen);
}
public class StringTest {
public static void methode(String sInnen, String tInnen) {
sInnen = "World";
tInnen.toUpperCase();
System.out.println(sInnen);
System.out.println(tInnen);
}
public static void main(String[] args) {
String sAussen = "Hello";
String tAussen = "klein";
methode(sAussen, tAussen);
System.out.println(sAussen);
System.out.println(tAussen);
}
}
main
sAussen
"Hello"
tAussen
"klein"
™ Überlegen Sie, welche Ausgabe das Programm erzeugt,
und prüfen Sie dann Ihre Vorhersage. Wie ist das Verhalten
zu erklären?
Java-Einführungskurs
21
Java-Einführungskurs
22
Ü4.4 Referenzen in methode
Ü4.4 Referenzen nach Rückkehr
public static void methode(String sInnen, String tInnen) {
sInnen = "World";
tInnen.toUpperCase();
System.out.println(sInnen);
System.out.println(tInnen);
}
public static void main(String[] args) {
String sAussen = "Hello";
String tAussen = "klein";
methode(sAussen, tAussen);
System.out.println(sAussen);
System.out.println(tAussen);
}
main
sAussen
main
"Hello"
tAussen
"klein"
sAussen
methode
sInnen
sInnen
"Hello"
tAussen
"klein"
methode
tInnen
"World"
tInnen
sInnen
"KLEIN"
World
klein
sInnen
tInnen
"World"
tInnen
main
sAussen
"KLEIN"
World
klein
tAussen
Hello
klein
Java-Einführungskurs
23
Lehrstuhl für Angewandte Telematik/e-Business
Java-Einführungskurs
24
4
26.03.2004
Ü4.4 Begründung
Pause
public class StringTest {
public static void methode(String sInnen, String tInnen) {
sInnen = "World";
tInnen.toUpperCase(); // neues "KLEIN" nicht gespeichert
System.out.println(sInnen); // "World"
System.out.println(tInnen); // "klein"
}
public static void main(String[] args) {
String sAussen = "Hello";
String tAussen = "klein";
methode(sAussen, tAussen);
System.out.println(sAussen); // "Hello"
System.out.println(tAussen); // "klein"
}
}
„Take a break...

ž
Ÿ
¨
• Merke: Methoden, Zuweisungen und Konkatenationen
ändern nicht den Inhalt des betroffenen String-Objekts,
sondern geben ein neues String-Objekt zurück!
Java-Einführungskurs
...have a steaming cup of Java!“
25
Lehrstuhl für Angewandte Telematik/e-Business
Java-Einführungskurs
26
5
Herunterladen