Donnerstag ist Exception Tag, im heutigen Teil der Java 7 Neuerungen geht es um ein erweitertes Exception Handling, eine kleine Verbesserung aus dem Project Coin. Es heißt übrigends deshalb Project Coin, da das Wort Coin für Kleingeld, Körberlgeld steht und somit nur als kleine Beigaben zu sehen sind. Interessanterweise finden gerade diese Neuerungen überall am meisten Gehör. Vielleicht weil sie sich schnell und knackig präsentieren lassen, wie hier in meinem Blog. Oder weil sie wohl für die breite Masse der Entwickler von Anfänger bis alten Hasen relevant sein werden.
Multi-Catch Exception
Musste bisher jede Exception einzeln abgefangen werden:
try{ functionWithException(); } catch (FileNotFoundException fnfe) { fnfe.printStackTrace(); } catch (IOException ioe) { ioe.printStackTrace(); }
konnte s zu redundanten Fehlerbehandlungen kommen, wo eine Verallgemeinerung der Exception nicht zielführend war. In Java 7 lassen sich nun mehrere ExceptionTypen in einer catch-Klausel fangen
try{ functionWithException(); } catch (FileNotFoundException | IOException e) { e.printStackTrace(); }
Präzisere Exceptions
Fängt man eine Exception oder ein Throwable (also eine Generische Exception) in einem catch Block mit einem vorgestellten final ab, kann man eine weitere Exception werfen lassen, diese wird dabei jedoch zur Compilezeit präzisiert. D.h. es wird ermittelt welche exakte Exception/Thorwable auftreten kann. Es reicht damit aus diese an der Methodendeklaration zu nennen.
public void getTheThrow() throws ThrowableA, ThrowableB{ try { throwAorB(); } catch (final Throwable t) { throw t; // throws a named exception, not Throwable } }
Dadurch bleibt die Behandlung im Code allgemein, und für denjenigen der die Methode einmal verwendet wurde jedoch die API eingeschränkt. Vor Java 7 hätte man hierbei einen Compile-Error erhalten.
Happy Coding
Lieber Thomas,
den Teil mit den „präziseren Exceptions“ habe ich leider nicht kapiert.
In Java sind Exceptions doch Objekte, wie der meiste Rest (Ausnahme: elementare
Typen) auch.
Somit erzeugt bei mir folgender Code:
public static void throwExc()
{
if ( Math.random() > 0.5 )
{
throw new IllegalArgumentException();
}
else
{
throw new AssertionError();
}
}
(sinnlos, zugegeben, aber sei’s drum) in folgendem Catch-Block aufgefangen:
try
{
throwExc();
}
catch ( Throwable t )
{
throw t;
}
immer den passenden Typ, auch mit Java 6. Und 5. und 1.4. etc.
Das liegt daran, dass das Objekt ja seinen Typ nicht ändert, nur weil
man „Throwable“ davor schreibt. Die Exception bleibt genau das, was
sie war.
Wie alle Objekte übrigens, wenn man sie castet und nichts anderes passiert
hier ja. Eigentlich steht hier ja:
throw (Throwable) new AssertionError();
Ändert nix an der Tatsache, dass das Objekt vom Typ AssertionError ist und nicht
vom Typ Throwable. „Throwable“ ist lediglich die Referenzvariable.
Nun frage ich mich, in welche Richtung Dein Hinweis gehen sollte oder was nun
die phänomenale Neuerung in Java 7 ist?!?
Liebe Grüße aus Stuttgart,
Roman
Hallo Roman!
Danke für dein Kommentar, du hast in der Tat recht, ich schreib hier von präziseren Exceptions und bin dabei selbst nicht genau genug gewesen.
Ich habe bereits entsprechende Anpassungen im Artikel vorgenommen, möchte es hier aber auch nochmal anführen.
Dadurch dass wir Throwable final gecatched haben, wird bereits beim compilen ermittelt welche Exceptions hierbei auftreten können. Daher reicht es aus, wenn wir Throwable t erneut werfen, und im Methodenaufruf bereits die präzieseren Exceptions unter throws aufführen:
Zu deinem Beispiel wäre das also ein:
Vor Java 7 würdest du hierbei einen Compilefehler erhalten:
Unhandled exception type Throwable
Ich hoffe damit alles geklärt zu haben, du kannst dich gern nochmal bei mir melden so noch weitere Fragen offen sind.
Schöne Grüße
Thomas