Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Exceptions
7 Äußere.innere Klassen
8 Besondere Klassen der Java SE
9 Generics<T>
10 Architektur, Design und angewandte Objektorientierung
11 Die Klassenbibliothek
12 Einführung in die nebenläufige Programmierung
13 Einführung in Datenstrukturen und Algorithmen
14 Einführung in grafische Oberflächen
15 Einführung in Dateien und Datenströme
16 Einführung in die <XML>-Verarbeitung mit Java
17 Einführung ins Datenbankmanagement mit JDBC
18 Bits und Bytes und Mathematisches
19 Die Werkzeuge des JDK
A Die Klassenbibliothek
Stichwort

Download:
- Aufgaben, ca. 1,1 MB
- Programme, ca. 12,8 MB

Buch bestellen
Ihre Meinung?

Spacer
Java ist auch eine Insel von Christian Ullenboom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
Galileo Computing
1308 S., 10., aktualisierte Auflage, geb., mit DVD
ca. 49,90 Euro, ISBN 978-3-8362-1802-3
Pfeil 6 Exceptions
Pfeil 6.1 Problembereiche einzäunen
Pfeil 6.1.1 Exceptions in Java mit try und catch
Pfeil 6.1.2 Eine NumberFormatException auffangen
Pfeil 6.1.3 Ablauf einer Ausnahmesituation
Pfeil 6.1.4 Eigenschaften vom Exception-Objekt
Pfeil 6.1.5 Wiederholung abgebrochener Bereiche *
Pfeil 6.1.6 Mehrere Ausnahmen auffangen
Pfeil 6.1.7 throws im Methodenkopf angeben
Pfeil 6.1.8 Abschlussbehandlung mit finally
Pfeil 6.2 RuntimeException muss nicht aufgefangen werden
Pfeil 6.2.1 Beispiele für RuntimeException-Klassen
Pfeil 6.2.2 Kann man abfangen, muss man aber nicht
Pfeil 6.3 Die Klassenhierarchie der Fehler
Pfeil 6.3.1 Die Exception-Hierarchie
Pfeil 6.3.2 Oberausnahmen auffangen
Pfeil 6.3.3 Schon gefangen?
Pfeil 6.3.4 Alles geht als Exception durch
Pfeil 6.3.5 Zusammenfassen gleicher catch-Blöcke mit dem multi-catch
Pfeil 6.4 Harte Fehler: Error *
Pfeil 6.5 Auslösen eigener Exceptions
Pfeil 6.5.1 Mit throw Ausnahmen auslösen
Pfeil 6.5.2 Vorhandene Runtime-Fehlertypen kennen und nutzen
Pfeil 6.5.3 Parameter testen und gute Fehlermeldungen
Pfeil 6.5.4 Neue Exception-Klassen deklarieren
Pfeil 6.5.5 Eigene Ausnahmen als Unterklassen von Exception oder RuntimeException?
Pfeil 6.5.6 Ausnahmen abfangen und weiterleiten *
Pfeil 6.5.7 Aufrufstack von Ausnahmen verändern *
Pfeil 6.5.8 Präzises rethrow *
Pfeil 6.5.9 Geschachtelte Ausnahmen *
Pfeil 6.6 Automatisches Ressourcen-Management (try mit Ressourcen)
Pfeil 6.6.1 try mit Ressourcen
Pfeil 6.6.2 Ausnahmen vom close() bleiben bestehen
Pfeil 6.6.3 Die Schnittstelle AutoCloseable
Pfeil 6.6.4 Mehrere Ressourcen nutzen
Pfeil 6.6.5 Unterdrückte Ausnahmen *
Pfeil 6.7 Besonderheiten bei der Ausnahmebehandlung *
Pfeil 6.7.1 Rückgabewerte bei ausgelösten Ausnahmen
Pfeil 6.7.2 Ausnahmen und Rückgaben verschwinden: Das Duo »return« und »finally«
Pfeil 6.7.3 throws bei überschriebenen Methoden
Pfeil 6.7.4 Nicht erreichbare catch-Klauseln
Pfeil 6.8 Den Stack-Trace erfragen *
Pfeil 6.8.1 StackTraceElement
Pfeil 6.8.2 printStackTrace()
Pfeil 6.8.3 StackTraceElement vom Thread erfragen
Pfeil 6.9 Assertions *
Pfeil 6.9.1 Assertions in eigenen Programmen nutzen
Pfeil 6.9.2 Assertions aktivieren
Pfeil 6.10 Zum Weiterlesen

Rheinwerk Computing - Zum Seitenanfang

6.7 Besonderheiten bei der Ausnahmebehandlung *Zur nächsten Überschrift

Bei der Ausnahmebehandlung gibt es ein paar Überraschungen, die vier Abschnitte gesondert vorstellen.


Rheinwerk Computing - Zum Seitenanfang

6.7.1 Rückgabewerte bei ausgelösten AusnahmenZur nächsten ÜberschriftZur vorigen Überschrift

Java versucht, durch den Programmfluss den Ablauf innerhalb einer Methode zu bestimmen und zu melden, ob sie definitiv einen Rückgabewert liefert. Dabei verfolgt der Compiler die Programmpfade und wertet bestimmte Ausdrücke aus. Doch die Aussage »Jede Methode mit einem Ergebnistyp ungleich void muss eine return-Anweisung besitzen« müssen wir etwas relativieren. Nur in einem speziellen Fall müssen wir dies nicht: nämlich genau dann, wenn vor dem Ende der Methode eine throw-Anweisung die Abarbeitung beendet:

Listing 6.25: NoReturn.java

class Windows7KeyGenerator
{
public String generateKey()
{
throw new UnsupportedOperationException();
}
}

Ein Blick auf generateKey() verrät, dass trotz eines angekündigten Rückgabewerts keine return-Anweisung im Rumpf steht. Die Abarbeitung wird vor dem Rücksprung durch eine Exception abgebrochen. generateKey() muss diese Exception nicht mit throws ankündigen, da UnsupportedOperationException eine RuntimeException ist.


Rheinwerk Computing - Zum Seitenanfang

6.7.2 Ausnahmen und Rückgaben verschwinden: Das Duo »return« und »finally«Zur nächsten ÜberschriftZur vorigen Überschrift

Ein Phänomen in der Ausnahmebehandlung von Java ist eine return-Anweisung innerhalb eines finally-Blocks. Zunächst einmal »überschreibt« ein return im finally-Block den Rückgabewert eines return im try-Block:

static String getIsbn()
{
try {
return "3821829877";
}
finally {
return "";
}
}

Der Aufrufer empfängt immer einen leeren String.

Interessant ist auch folgendes Programm:

public static int a()
{
while ( true )
{
try {
return 0;
}
finally {
break;
}
}

return 1;
}

Die Ausgabe auf der Konsole ist 1. Das break im finally lässt die Laufzeitumgebung aus der Schleife austreten und den Rückgabewert ignorieren.

Ein weiteres Kuriosum sind Ausnahmen. Die Laufzeitumgebung gibt bei einer return-Anweisung im finally-Block eine im try-Block ausgelöste Ausnahme nicht zum Aufrufer weiter, sondern bietet einfach die Rückgabe an.

Die folgende Methode löst zum Beispiel eine RuntimeException aus, die aber der Aufrufer der Methode nie sieht:

static void obamaVsMcCain()
{
try {
throw new RuntimeException();
}
finally
{
return;
}
}

Entfernen wir die Zeile mit dem return, ist das Verhalten der Laufzeitumgebung wie erwartet.

Abbildung
Der Java-Compiler von Eclipse markiert die Diskrepanz und zeigt eine Warnung an (»finally block does not complete normally«). Mit der Annotation @SuppressWarnings("finally") schalten wir diesen Hinweis ab.


Rheinwerk Computing - Zum Seitenanfang

6.7.3 throws bei überschriebenen MethodenZur nächsten ÜberschriftZur vorigen Überschrift

Beim Überschreiben von Methoden gibt es eine wichtige Regel: Überschriebene Methoden in einer Unterklasse dürfen nicht mehr Ausnahmen auslösen, als schon beim throws-Teil der Oberklasse aufgeführt sind. Da das gegen das Substitutionsprinzip verstieße, kann eine Methode der Unterklasse nur

  • dieselben Ausnahmen wie die Oberklasse auslösen,
  • Ausnahmen spezialisieren oder
  • weglassen.

Dazu sehen wir hier ein konstruiertes Beispiel für die beiden letzten Fälle:

Listing 6.26: ExceptionlessRandomAccessFile.java

import java.io.*;
import java.net.ProtocolException;

public class ExceptionlessRandomAccessFile extends RandomAccessFile
{
public ExceptionlessRandomAccessFile( File file, String mode )
throws FileNotFoundException
{
super( file, mode );
}

@Override
public long length()
{
try
{
return super.length();
}
catch ( IOException e )
{
return 0;
}
}

@Override
public void write( int b ) throws ProtocolException
{
try
{
super.write( b );
}
catch ( IOException e )
{
throw new ProtocolException();
}
}
}

Die Methoden length() und write() lösen in RandomAccessFile eine IOException aus. Unsere Unterklasse ExceptionlessRandomAccessFile überschreibt zunächst length() und lässt die Ausnahme in der Signatur weg. Das hat in der Nutzung einige Folgen, denn wenn wir die Klasse als ExceptionlessRandomAccessFile der Art

ExceptionlessRandomAccessFile raf = ...
raf.length();

verwenden, muss die nicht vorhandene zu prüfende Ausnahme von length() ebenfalls nicht abgefangen werden – und darf es auch gar nicht, weil ein try-catch auf eine IOException zu einem Compilerfehler führt.

Umgekehrt: Ist raf vom Typ der Basisklasse RandomAccessFile, muss die Ausnahme auf jeden Fall abgefangen werden:

RandomAccessFile raf = ...;
try
{
raf.length();
}
catch ( IOException e ) { }

Das zeigt die Schwierigkeit bei überschriebenen Methoden, die Ausnahmen weglassen.

Bei der Methode write() führt throws den Ausnahmetyp ProtocolException als Unterklasse von IOException auf. Natürlich reicht es nicht aus, in write() einfach super.write() stehen zu lassen (was nur eine allgemeinere IOException auslösen würde, aber nicht die versprochene speziellere ProtocolException). Daher fangen wir im Rumpf der Methode das super.write() ab und erzeugen die speziellere ProtocolException.

Design

Wenn demnach eine überschriebene Methode der Unterklasse keine geprüften Fehler hinzufügen kann, muss das Design der Basistypen so entworfen sein, dass Unterklassen notwendige Fehler melden können.


Rheinwerk Computing - Zum Seitenanfang

6.7.4 Nicht erreichbare catch-KlauselnZur nächsten ÜberschriftZur vorigen Überschrift

Eine catch-Klausel heißt erreichbar, wenn es in dem try- und catch-Block eine Anweisung gibt, die die in der catch-Klausel abgefangene Fehlerart tatsächlich auslösen kann. Zusätzlich darf vor dieser catch-Klausel natürlich kein anderes catch stehen, das diesen Fehlerfall mit abfängt. Wenn wir zum Beispiel catch(Exception e) als erstes Auffangbecken bereitstellen, werden natürlich alle Ausnahmen dort behandelt. Die Konsequenz daraus: catch-Klauseln sollten immer von den speziellen zu den allgemeinen Fehlerarten sortiert werden.

Wenn wir ein Objekt RandomAccessFile aufbauen und anschließend readLine() verwenden, so muss eine FileNotFoundException vom Konstruktor und eine IOException von readLine() abgefangen werden. Da eine FileNotFoundException eine Spezialisierung ist, also eine Unterklasse von IOException, würde ein catch(IOException e) schon reichen. Steht im Quellcode folglich der catch für die FileNotFoundException dahinter, wird der Teil nie ausgeführt werden können, und der Compiler merkt das zu Recht an.

Übertriebene throws-Klauseln

Eine Methode compiliert, auch wenn sie zu viele oder zu allgemeine Fehlerarten in ihrer throws-Klausel angibt:

Listing 6.27: TooManyExceptions.java, openFile()

void openFile() throws FileNotFoundException,
IOException,
InterruptedException
{
new RandomAccessFile( "", "" );
}

Unsere Methode openFile() ruft den Konstruktor von RandomAccessFile auf, was bekannterweise zu einer FileNotFoundException führen kann. openFile() jedoch gibt neben FileNotFoundException noch die allgemeinere Oberklasse IOException an und meldet mit InterruptedException noch eine geprüfte Ausnahme, die der Rumpf überhaupt auslöst. Trotzdem lässt der Compiler das durch.

Beim Aufruf solcher Methoden in try-Blöcken müssen in den catch-Klauseln die zu viel deklarierten Exceptions aufgefangen werden, auch wenn sie nicht wirklich erreicht werden können:

Listing 6.28: TooManyExceptions.java, useFile()

try
{
openFile();
}
catch ( IOException e ) { }
catch ( InterruptedException e ) { }

Der Sinn besteht darin, dass dies später in einer Erweiterung einer Methode, etwa einer InterruptedException, durchaus vorkommen kann, und dann sind die Aufrufer darauf schon vorbereitet.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Java ist auch eine Insel





Java ist auch eine Insel
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Katalog: Java SE Bibliotheken






 Java SE Bibliotheken


Zum Katalog: Professionell entwickeln mit Java EE 7






 Professionell
 entwickeln mit
 Java EE 7


Zum Katalog: Einstieg in Eclipse






 Einstieg in
 Eclipse


Zum Katalog: Einstieg in Java






 Einstieg in
 Java


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2011
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de