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

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Generics, innere Klassen
10 Die Klassenbibliothek
11 Threads und nebenläufige Programmierung
12 Datenstrukturen und Algorithmen
13 Raum und Zeit
14 Dateien und Datenströme
15 Die eXtensible Markup Language (XML)
16 Grafische Oberflächen mit Swing
17 Grafikprogrammierung
18 Netzwerkprogrammierung
19 Verteilte Programmierung mit RMI und Web–Services
20 JavaServer Pages und Servlets
21 Applets
22 Midlets und die Java ME
23 Datenbankmanagement mit JDBC
24 Reflection und Annotationen
25 Logging und Monitoring
26 Sicherheitskonzepte
27 Java Native Interface (JNI)
28 Dienstprogramme für die Java-Umgebung
Stichwort

Download:
- ZIP, ca. 14,1 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel (8. Auflage) von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel (8. Auflage)

Java ist auch eine Insel (8. Aufl.)
8., aktual. Auflage, geb., mit DVD
1.475 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1371-4
Pfeil 8 Exceptions
Pfeil 8.1 Problembereiche einzäunen
Pfeil 8.1.1 Exceptions in Java mit try und catch
Pfeil 8.1.2 Eine Datei mit RandomAccessFile auslesen
Pfeil 8.1.3 Ablauf einer Ausnahmesituation
Pfeil 8.1.4 Wiederholung abgebrochener Bereiche
Pfeil 8.1.5 throws im Methodenkopf angeben
Pfeil 8.1.6 Abschlussbehandlung mit finally
Pfeil 8.1.7 Nicht erreichbare catch-Klauseln
Pfeil 8.2 Die Klassenhierarchie der Fehler
Pfeil 8.2.1 Die Exception-Hierarchie
Pfeil 8.2.2 Oberausnahmen auffangen
Pfeil 8.2.3 Alles geht als Exception durch
Pfeil 8.2.4 RuntimeException muss nicht aufgefangen werden
Pfeil 8.2.5 Harte Fehler: Error
Pfeil 8.3 Auslösen eigener Exceptions
Pfeil 8.3.1 Mit throw Ausnahmen auslösen
Pfeil 8.3.2 Neue Exception-Klassen deklarieren
Pfeil 8.3.3 Abfangen und Weiterleiten
Pfeil 8.3.4 Geschachtelte Ausnahmen
Pfeil 8.4 Rückgabewerte bei ausgelösten Ausnahmen
Pfeil 8.5 Der Stack-Trace
Pfeil 8.5.1 Stack-Trace erfragen
Pfeil 8.6 Assertions
Pfeil 8.6.1 Assertions in eigenen Programmen nutzen
Pfeil 8.6.2 Assertions aktivieren


Galileo Computing - Zum Seitenanfang

8.3 Auslösen eigener Exceptions Zur nächsten ÜberschriftZur vorigen Überschrift

Bisher wurden Exceptions lediglich aufgefangen, aber noch nicht selbst erzeugt. In diesem Abschnitt wollen wir sehen, wie eigene Ausnahmen ausgelöst werden. Das kann zum einen erfolgen, wenn die JVM provoziert wird, etwa bei einer ganzzahligen Division durch 0 oder explizit durch throw.


Galileo Computing - Zum Seitenanfang

8.3.1 Mit throw Ausnahmen auslösen Zur nächsten ÜberschriftZur vorigen Überschrift

Soll eine Methode oder ein Konstruktor selbst eine Exception auslösen, muss zunächst ein Exception-Objekt erzeugt und dann die Ausnahmebehandlung angestoßen werden. Im Sprachschatz dient das Schlüsselwort throw dazu, eine Ausnahme zu signalisieren und die Abarbeitung an der Stelle zu beenden.

Als Exception-Typ soll im folgenden Beispiel IllegalArgumentException dienen, das ein fehlerhaftes Argument anzeigt.

Listing 8.10 com/tutego/insel/exceptions/v1/Player.java, Konstruktor

Player( int age ) 
{ 
  if ( age <= 0 ) 
    throw new IllegalArgumentException( "No age <= 0 allowed!" ); 
 
  this.age = age; 
}

Wir sehen im Beispiel, dass negative oder null Alter-Übergaben nicht gestattet sind und zu einem Fehler führen. Im ersten Schritt baut dazu der new-Operator das Exception-Objekt über einen parametrisierten Konstruktor auf. Die Klasse IllegalArgumentException bietet einen solchen Konstruktor, der eine Zeichenkette annimmt, die den näheren Grund der Ausnahme übermittelt. Welche Parameter die einzelnen Exception-Klassen deklarieren, ist der API zu entnehmen. Nach dem Aufbau des Exception-Objekts beendet throw die lokale Abarbeitung, und die JVM sucht ein catch, das die Ausnahme behandelt.


Hinweis Ein throws IllegalArgumentException ist in diesem Beispiel überflüssig, da IllegalArgumentException eine RuntimeException ist, die nicht über ein throws in der Methoden-Signatur angegeben werden muss.


Lassen wir ein Beispiel folgen, in dem Spieler mit einem negativen Alter initialisiert werden sollen:

Listing 8.11 com/tutego/insel/exceptions/v1/Player.java, main()

try 
{ 
  Player d = new Player( –100 ); 
  System.out.println( d ); 
} 
catch ( IllegalArgumentException e ) 
{ 
  e.printStackTrace(); 
}

Das führt zu einer Exception, und der Stack-Trace, der den printStackTrace() ausgibt, ist:

java.lang.IllegalArgumentException: No age <= 0 allowed! 
  at com.tutego.insel.exceptions.v1.Player.<init>(Player.java:10) 
  at com.tutego.insel.exceptions.v1.Player.main(Player.java:19)

Hinweis Löst ein Konstruktor eine Ausnahme aus, ist eine Nutzung wie die folgende problematisch:

Player p = null; 
try { p = new Player(v); } catch ( IllegalArgumentException e ) { } 
p.getAge();   // (*) BUMM!

Die Exception führt zu keinem Player-Objekt, wenn v negativ ist. So bleibt p mit null vorbelegt. Es folgt in der BUMM-Zeile eine NullPointerException. Der Programmcode, der das Objekt erwartet, sollte also mit in den try-catch-Block.


Da die IllegalArgumentException eine RuntimeException ist, hätte es in main() auch ohne try-catch heißen können:

public static void main( String[] args ) 
{ 
  Player d = new Player( –100 ); 
}

Die Runtime-Exception müsste nicht zwingend aufgefangen werden, aber der Effekt wäre, dass die Ausnahme nicht behandelt würde und das Programm abbräche.


class java.lang.IllegalArgumentException 
extends RuntimeException

  • IllegalArgumentException()
    Erzeugt eine neue Ausnahme ohne genauere Fehlerangabe.
  • IllegalArgumentException( String s )
    Erzeugt ein neues Fehler-Objekt mit einer detaillierteren Fehlerangabe.

Galileo Computing - Zum Seitenanfang

8.3.2 Neue Exception-Klassen deklarieren Zur nächsten ÜberschriftZur vorigen Überschrift

Eigene Exceptions sind immer direkte (oder indirekte) Unterklassen von Exception. Sie im-plementieren oft zwei Konstruktoren: einen Standard-Konstruktor und einen mit einem String parametrisierten Konstruktor. Um für die Klasse Player im letzten Beispiel einen neuen Fehlertyp zu deklarieren, erweitern wir RuntimeException zur PlayerException.

Listing 8.12 com/tutego/insel/exception/v2/PlayerException.java

package com.tutego.insel.exception.v2; 
 
public class PlayerException extends RuntimeException 
{ 
  public PlayerException() 
  { 
  } 
 
  public PlayerException( String s ) 
  { 
    super( s ); 
  } 
}

Nehmen wir uns die Initialisierung mit dem Alter noch einmal vor. Statt der IllegalArgumentException löst der Konstruktor im Fehlerfall unsere speziellere PlayerException aus.

Listing 8.13 com/tutego/insel/exception/v2/Player.java, Ausschnitt

if ( age <= 0 ) 
  throw new PlayerException( "No age <= 0 allowed!" );

Im Hauptprogramm können wir auf die PlayerException reagieren, indem wir die Ausnahme explizit mit try-catch auffangen oder an den Aufrufer weitergeben – unsere Exception ist ja eine RuntimeException und müsste nicht direkt abgefangen werden.

Exception in thread "main" com.tutego.insel.exceptions.v2.PlayerException: Zeilen-Umbruch 
  No age <= 0 allowed! 
  at com.tutego.insel.exceptions.v2.Player.<init>(Player.java:10) 
  at com.tutego.insel.exceptions.v2.Player.main(Player.java:19)

Tipp Es ist immer eine gute Idee, Unterklassen von Exception zu bauen. Würden wir keine Unterklassen anlegen, sondern direkt mit throw new Exception() einen Fehler anzeigen, so könnten wir unseren Fehler später nicht mehr von anderen Fehlern unterscheiden. Mit der Hierarchiebildung wird nämlich die Spezialisierung bei mehreren catch-Anweisungen sowie eine Unterscheidung mit instanceof unterstützt. Wir müssen immer unseren Fehler mit catch(Exception e) auffangen und bekommen so alle anderen Fehler mit aufgefangen, die dann nicht mehr unterschieden werden können. Allerdings sollten Entwickler nicht zu inflationär mit den Ausnahmen-Hierarchien umgehen; in vielen Fällen reicht eine Standard-Ausnahme aus.



Galileo Computing - Zum Seitenanfang

8.3.3 Abfangen und Weiterleiten Zur nächsten ÜberschriftZur vorigen Überschrift

Die Ausnahme, die ein try-catch-Block auffängt, kann in catch wieder neu ausgelöst werden. Dieses Re-Throwing zeigt folgendes Beispiel, in dem das Programm den Fehler erst über einen Logger ausgibt und dann weiter nach oben reicht.

Listing 8.14 Rethrow.java

import java.util.logging.Logger; 
 
public class Rethrow 
{ 
  private static Logger log = Logger.getAnonymousLogger(); 
 
  static void rethrow( RuntimeException e ) 
  { 
    log.warning( "RuntimeException occurred!" ); 
 
//    e.fillInStackTrace(); 
 
    throw e; 
  } 
 
  public static void main( String[] args ) 
  { 
    try 
    { 
      ((String)null).length(); 
    } 
    catch ( NullPointerException e ) 
    { 
      rethrow( e ); 
    } 
  } 
}

Die Ausgabe ist:

16.08.2006 18:35:27 Rethrow rethrow 
WARNUNG: RuntimeException occurred! 
Exception in thread "main" java.lang.NullPointerException 
  at Rethrow.main(Rethrow.java:20)

Wichtig an dieser Stelle ist die Tatsache, dass der Aufrufstack in e gespeichert ist und daher der Stack-Trace nicht die Funktion rethrow() enthält. Wünschten wir dies, müssen wir den Stack-Trace neu füllen. Dazu dient die Methode fillInStackTrace(). Nehmen wir den Aufruf im oberen Beispiel hinein, folgt die Ausgabe:

16.08.2006 18:36:16 Rethrow rethrow 
WARNUNG: RuntimeException occurred! 
Exception in thread "main" java.lang.NullPointerException 
  at Rethrow.rethrow(Rethrow.java:11) 
  at Rethrow.main(Rethrow.java:24)

Galileo Computing - Zum Seitenanfang

8.3.4 Geschachtelte Ausnahmen topZur vorigen Überschrift

Der Grund für eine Ausnahme mag der sein, dass ein eingebetteter Teil versagt. Das ist vergleichbar mit einer Transaktion: Ist ein Teil der Kette fehlerhaft, so ist der ganze Teil nicht ausführbar. Bei Ausnahmen ist das nicht anders. Nehmen wir an, wir haben eine Methode foo(), die im Falle eines Misslingens eine Ausnahme HellException auslöst. Ruft unsere Methode foo() nun ein Unterprogramm bar() auf, das zum Beispiel eine Ein-/Ausgabeoperation tätigt, und das geht schief, wird der Anlass für unsere HellException die IO-Exception sein. Es liegt also nahe, bei der Nennung des Grundes für das eigene Versagen das Misslingen der Unteraufgabe zu nennen. (Wieder ein Beweis, wie »menschlich« Programmieren sein kann.)

Eine geschachtelte Ausnahme (engl. nested exception) speichert einen Verweis auf eine weitere Ausnahme. Wenn ein Exception-Objekt aufgebaut wird, lässt sich der Grund (engl. cause) als Argument im Konstruktor der Throwable-Klasse übergeben. Die Ausnahme-Basisklasse bietet dafür zwei Konstruktoren:

  • Throwable( Throwable cause )
  • Throwable( String message, Throwable cause )

Der Grund kann über die Methode Throwable getCause() erfragt werden.

Da Konstruktoren in Java nicht vererbt werden, bieten die Unterklassen oft Konstruktoren an, um den Grund anzunehmen: Zumindest Exception macht das und kommt somit auf vier Erzeuger:

  • Exception()
  • Exception( String message )
  • Exception( String message, Throwable cause )
  • Exception( Throwable cause )

Einige der tieferliegenden Unterklassen haben dann auch diese Konstruktor-Typen mit Throw-able-Parameter, wie IOException, SQLException oder ClassNotFoundException, andere wiederum nicht, wie PrinterException. Eigene Unterklassen können auch mit initCause() genau einmal eine geschachtelte Ausnahme angeben.

In modernen Frameworks ist die Nutzung von Ausnahmen, die nicht geprüft werden müssen, also Exemplare von RuntimeException sind, häufiger geworden. Bekannte zu prüfende Ausnahmen werden in RuntimeException-Objekte verpackt (eine Art Exception-Wrapper), die den Verweis auf die auslösende Nicht-RuntimeException speichern.



Ihr Kommentar

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






<< 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

 Tipp
Zum Katalog: Coding for Fun





 Coding for Fun


 Buchempfehlungen
Zum Katalog: Objektorientierte Programmierung





 Objektorientierte
 Programmierung


Zum Katalog: Einstieg in Eclipse 3.4






 Einstieg in
 Eclipse 3.4


Zum Katalog: Java 6 lernen mit Eclipse






 Java 6 lernen
 mit Eclipse


Zum Katalog: NetBeans Platform 6






 NetBeans
 Platform 6


Zum Katalog: Java und XML






 Java und XML


Zum Katalog: Visual C# 2008






 Visual C# 2008


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: C++ von A bis Z






 C++ von A bis Z


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2009
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.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de