Ausnahmen in Java erneut auslösen, ohne den Stack-Trace zu verlieren


417

In C # kann ich die throw;Anweisung verwenden, um eine Ausnahme erneut auszulösen, während die Stapelverfolgung beibehalten wird:

try
{
   ...
}
catch (Exception e)
{
   if (e is FooException)
     throw;
}

Gibt es so etwas in Java ( das den ursprünglichen Stack-Trace nicht verliert )?


4
Warum verliert es Ihrer Meinung nach die ursprüngliche Stapelspur? Die einzige Möglichkeit, es zu verlieren, wenn Sie eine neue SomeOtherException auslösen und vergessen, die Grundursache im Konstruktor oder in initCause () zuzuweisen.
Akarnokd

4
Ich glaube, so verhält sich der Code in .Net, aber ich bin nicht mehr positiv. Es könnte sich lohnen, entweder irgendwo nachzuschlagen oder einen kleinen Test durchzuführen.
Ripper234

11
Throwables werden nicht durch Werfen verändert. Um den Stack-Trace zu aktualisieren, müssen Sie aufrufen fillInStackTrace(). Praktischerweise wird diese Methode im Konstruktor von a aufgerufen Throwable.
Robert

50
In C # throw e;verliert ja die Stapelspur. Aber nicht in Java.
Tim Goodman

Antworten:


560
catch (WhateverException e) {
    throw e;
}

wird einfach die Ausnahme erneut auslösen, die Sie abgefangen haben (offensichtlich muss die umgebende Methode dies über ihre Signatur usw. zulassen). Die Ausnahme behält die ursprüngliche Stapelverfolgung bei.


4
Hallo, InterruptedException e gibt eine nicht behandelte Ausnahmemeldung aus, wenn ich die Zeile throw e hinzufüge. Nicht so, wenn ich es durch die breitere Ausnahme ersetze. E. Wie soll das richtig gemacht werden?
James P.

1
@James, ich habe gerade beobachtet, dass die Nachricht verschwindet, wenn in der Funktionsdeklaration "löst XxxException aus" hinzugefügt wird.
Shiouming

2
In Java 7 ist der Compiler für ein solches Umwerfen intelligenter. Jetzt funktioniert es gut mit bestimmten "Throws" -Ausnahmen in der enthaltenen Methode.
Waldemar Wosiński

192
@ James Wenn du catch(Exception e) { throw e; }das nicht behandeln wirst. Wenn Sie catch(InterruptedException ie) { throw ie; }es wird behandelt. Als Faustregel gilt catch(Exception e): Dies ist kein Pokemon, und wir wollen sie nicht alle fangen!
CorsiKa

3
@corsiKa Es ist nicht unbedingt wahr, dass Sie nicht "Catch 'em all" wollen, es ist nur ein anderer Anwendungsfall. Wenn Sie eine Schleife oder einen Ereignishandler der obersten Ebene haben (z. B. innerhalb eines Threads), wenn Sie nicht mindestens RuntimeException abfangen und protokollieren, verpassen Sie häufig die Ausnahme insgesamt UND brechen stillschweigend aus einer wichtigen Schleife aus ist oft ein einmaliger Fehler. Es ist auch sehr gut für Plugin-Funktionen geeignet, bei denen Sie nicht wissen, was zusätzlicher Code bewirken oder auslösen könnte ... Für Top-Down-Anwendungen wie diese ist eine Ausnahme oft nicht nur eine gute Idee, sondern auch eine bewährte Methode.
Bill K

82

Ich würde bevorzugen:

try
{
    ...
}
catch (FooException fe){
   throw fe;
}
catch (Exception e)
{
    // Note: don't catch all exceptions like this unless you know what you
    // are doing.
    ...
}

6
In Java auf jeden Fall geeignet, um bestimmte Ausnahmen zu erfassen, die nicht generisch sind und beispielsweise überprüft werden. +1
amischiefr

8
-1, weil Sie niemals eine einfache "Ausnahme" abfangen sollten, es sei denn, Sie wissen, was Sie tun.
Stroboskop

19
@Stroboskop: stimmt, aber um zu antworten, ist es am besten, den gleichen (ähnlichen) Code wie in der Frage zu verwenden!
user85421

14
Manchmal ist es in Ordnung, alle Ausnahmen zu fangen. Zum Beispiel, wenn Sie einen Testfall schreiben. Oder zu Protokollierungszwecken. Oder in der Hauptsache, wo nicht fangen bedeutet abstürzen.
John Henckel

1
@ JohnHenckel und andere: Gültige Punkte angegeben. Ich habe die Frage aktualisiert, um zu verdeutlichen, dass das Fangen Exceptionin den meisten (aber nicht allen) Fällen normalerweise nicht das Richtige ist .
Per Lundberg

74

Sie können die Ausnahme auch in eine andere umschließen UND die ursprüngliche Stapelverfolgung beibehalten, indem Sie die Ausnahme als Throwable als Ursachenparameter übergeben:

try
{
   ...
}
catch (Exception e)
{
     throw new YourOwnException(e);
}

8
Ich würde auch empfehlen, eine Nachricht nebenthrow new YourOwnException("Error while trying to ....", e);
Julien

Dies ist, wonach ich gesucht habe, insbesondere die Version aus dem ersten Kommentar, in der Sie Ihre eigene Nachricht weitergeben können
Csaba

Dies zeigt die Fehlermeldung korrekt an, aber die Stapelverfolgung zeigt die Fehlerzeile als Zeile mit 'throw new ....... (e)' und nicht als die ursprüngliche Zeile, die die Ausnahme verursacht hat.
Ashburn RK

22

In Java ist fast das gleiche:

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}

5
Nein, solange Sie kein neues Exception-Objekt instanziieren, bleibt die Stacktrace gleich.
Mnementh

28
Ich würde einen bestimmten Fang für FooException hinzufügen
dfa

3
In diesem speziellen Fall stimme ich zu, aber das Hinzufügen eines bestimmten Fangs ist möglicherweise nicht die richtige Wahl. Stellen Sie sich vor, Sie haben einen gemeinsamen Code für alle Ausnahmen und werfen ihn nach einer bestimmten Ausnahme erneut.
Alves

1
@ MarkusLausberg Aber endlich keine Ausnahmen.
Robert

Ja, aber das war nicht die Frage.
Markus Lausberg

14

In Java wird nur die Ausnahme ausgelöst, die Sie abgefangen haben, throw eund nicht nur throw. Java verwaltet den Stack-Trace.


6

etwas wie das

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}

5
public int read(byte[] a) throws IOException {
    try {
        return in.read(a);
    } catch (final Throwable t) {
        /* can do something here, like  in=null;  */
        throw t;
    }
}

Dies ist ein konkretes Beispiel, bei dem die Methode ein löst IOException. Das finalMittel tkann nur eine Ausnahme enthalten, die vom try-Block ausgelöst wird. Zusätzliches Lesematerial finden Sie hier und hier .



3

Die Stapelverfolgung wird beibehalten, wenn Sie die abgefangene Vervollständigung in eine andere Ausnahme einschließen (um weitere Informationen bereitzustellen) oder wenn Sie die abgefangene Vervollständigung nur erneut auslösen.

try{ ... }catch (FooException e){ throw new BarException("Some usefull info", e); }


2

Ich hatte gerade eine ähnliche Situation, in der mein Code möglicherweise eine Reihe verschiedener Ausnahmen auslöst, die ich nur neu werfen wollte. Die oben beschriebene Lösung hat bei mir nicht funktioniert, da Eclipse mir mitgeteilt hat, dass dies throw e;zu einer nicht gehandelten Ausnahme führt. Deshalb habe ich Folgendes getan:

try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {                    
    throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}

Arbeitete für mich .... :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.