2010-03-10 11 views

Antwort

47

Denn wenn Sie die Ausnahme fangen, sollten Sie damit richtig umgehen. Und Sie können nicht erwarten, alle Arten von Ausnahmen in Ihrem Code zu behandeln. Auch wenn Sie alle Ausnahmen abfangen, erhalten Sie möglicherweise eine Ausnahme, die nicht mit Code umgehen und verhindern kann, der im Stapel oben ist, um es ordnungsgemäß zu behandeln.

Das allgemeine Prinzip ist es, die spezifische Art möglich zu fangen.

+9

Zum Beispiel eine java.lang.InterruptedException ausgelöst wird, wenn ein Thread aufgefordert wird zu stoppen. Wenn sie abgefangen und ignoriert werden, kann die Threadverarbeitung nicht ordnungsgemäß beendet werden und Ihr Code wird nicht mehr in einem Arbeitsthread ausgeführt. Dies ist ein Beispiel, möglicherweise gibt es andere. – Pierre

+1

Ich bin ein großer Fan von Menschen, die ihre Rahmenbedingungen verstehen. Der Hauptgrund, warum dieser Ratschlag schrecklich ist, ist, dass 90% der Zeit, für die der Code, für den die Ausnahme geschrieben wird, an der Grenze ihrer API liegt. Ich stimme zu, dass Sie innerhalb einer API immer geeignete Ausnahmen abfangen sollten, aber wenn Sie an einer API-Grenze sind, fangen Sie bitte alles ab, was das System nicht zerstört. – coding

5

Da Sie nicht wirklich wissen, warum eine Ausnahme aufgetreten ist, und mehrere Ausnahmen erfordern sehr spezielle Auto (wenn überhaupt möglich), wie eine OutOfMemoryException und ähnliche Low-Level-Systemausnahmen.

Daher sollten Sie nur fangen Ausnahmen:

  • , die Sie genau wissen, wie sie damit umgehen (zB FileNotFoundException oder so)
  • wenn Sie sie danach wieder erhöhen (zum Beispiel Post auszuführen -fail Bereinigung)
  • , wenn Sie die Ausnahme von einem anderen Thread
+0

Es gibt keine OutOfMemoryException. Es gibt OutOfMemoryError unter Throwable hierarchy. –

+2

@EladTabak, Sie haben natürlich Recht in Bezug auf Java. Allerdings war das Tag "java" nicht vorhanden, als ich die Frage beantwortet habe (siehe [revision history] (http://stackoverflow.com/posts/2416316/revisions)), und die übermittelte Bedeutung ist trotzdem korrekt - unabhängig davon die tatsächliche Umgebung. – Lucero

5

Es hängt davon ab, transportieren müssen, was Sie brauchen. Wenn Sie verschiedene Arten von Ausnahmen auf unterschiedliche Weise behandeln müssen, sollten Sie mehrere catch-Blöcke verwenden und so viele spezifische Ausnahmen wie möglich abfangen.

Aber manchmal können Sie alle Ausnahmen in gleicher Weise behandeln müssen. In solchen Fällen kann catch (Exception) in Ordnung sein. Zum Beispiel:

try 
    { 
     DoSomething(); 
    } 
    catch (Exception e) 
    { 
     LogError(e); 
     ShowErrorMessage(e); // Show "unexpected error ocurred" error message for user. 
    } 
+2

Das ist kein gutes Muster zu folgen; Logging sollte nicht so gemacht werden, weil Sie für jede "Ebene" von try-catch ein paar gleiche Einträge erhalten. – Lucero

+0

Ich stimme zu, ich habe es nur als Beispiel benutzt. Kann nicht das beste Beispiel sein :) –

+1

@Lucero: Ich denke, es ist besser, ein Protokollierungs-Framework zu haben, das redundante Einträge konsolidieren kann, als davon ausgehen, dass, was auch immer Schicht behandelt (schlucken) eine Ausnahme wird es protokollieren. Außerdem, wenn Ausnahmen nicht so zahlreich sind, dass das mehrfache Protokollieren einen Leistungsengpass darstellen würde (in diesem Fall würde ich sagen * das ist ein Problem, das behoben werden muss), würde ich redundante Informationen im Protokoll sehen, die dann gefiltert werden könnten Ein Dienstprogramm zum Anzeigen von Protokollen wäre besser als ein übersichtlicheres Protokoll zu haben, dem die eine Information fehlt, die man benötigt. – supercat

8

Sie sollten nur Ausnahmen abfangen, wenn Sie sie richtig behandeln können. Wie Sie nicht richtig, alle möglichen Ausnahmen umgehen können, sollten Sie fangen sie nicht :-)

+8

Ein großes Problem mit diesem Denken ist, dass es viele Situationen gibt, in denen die richtige Handhabung für 99% der Ausnahmen die Meldung sein könnte, dass einige Aktionen nicht abgeschlossen werden können und mit dem Leben weitermachen, sondern jedes einzelne identifizieren Art der Ausnahme, für die dies der richtige Weg wäre, wäre schwierig, wenn nicht unmöglich. Zu schade, dass es keinen Mechanismus gibt, um "Exceptions erfüllen" von "CPU ist in Brand" -Ausnahmen zu unterscheiden. – supercat

+1

CPU ist in Brand und wird wahrscheinlich eine Art 'java.lang.Error' verursachen. – yegeniy

+0

> Ein Fehler ist eine Unterklasse von Throwable, die auf schwerwiegende Probleme hinweist, die eine sinnvolle Anwendung nicht zu erfassen versuchen sollte. – yegeniy

15

Kurzgeschichte: es Fehler Maskierung bezeichnet. Wenn Sie einen Code haben, der nicht gut funktioniert und Ausnahmen auslöst (oder Sie fehlerhafte Eingaben an diesen Codeabschnitt weitergeben) und Sie nur Ihre Augen blind machen, indem Sie alle möglichen Ausnahmen abfangen, werden Sie den Fehler tatsächlich nie aufdecken und beheben.

+0

Eine Ausnahme zu "fangen" heißt nicht, einfach weiterzumachen, als wäre nichts falsch. Ein "catch" -Block ist ein Code-Block, in dem du ** etwas ** tust. Das ** etwas ** könnte sein, Informationen über die Ausnahme zu protokollieren, über das, was der Benutzer getan hat, oder über den Status der Benutzeroberfläche, um Verbindungen und Dateien zu schließen, damit die App ordnungsgemäß beendet wird und um dem Benutzer mitzuteilen, was passiert ist. Wie ist das alles "maskieren"? – user316117

+0

@ user316117 'Exception' ist die oberste Klasse aller Ausnahmen in Java. Fangen bedeutet, dass Sie alle möglichen Fehler abfangen. Wie würdest du wissen, was in einem solchen Block zu tun ist? Wenn Sie auf einen bestimmten Fehler reagieren wollen, fangen Sie seine spezifische Ausnahme ab und arbeiten Sie damit. Es gibt keinen praktischen Nutzen, um alle möglichen Ausnahmen zu erfassen, außer um Ihre Augen zu blenden (und ich habe viele Kollegen gesehen, die das tun, weil sie am Ende des Arbeitstages nach Hause gehen wollen). – dimitarvp

+0

@dimitarvp Throwable ist die höchste Klasse aller Ausnahmen. Es hat zwei Unterklassen, die Ausnahmen in zwei Zweigen partitionieren. Einer von ihnen ist AUSNAHME und andere ist FEHLER. –

0

Dies kann Java-spezifisch sein:

In einigen Fällen müssen Sie Methoden aufrufen, die überprüft Ausnahmen werfen. Wenn dies in Ihrer EJB-/Business-Logik-Ebene ist, haben Sie zwei Möglichkeiten - fangen Sie sie ab oder werfen Sie sie erneut.

spezifische Ausnahmeklassen Fangen bedeutet, dass Sie Ihre Aktionen neu analysieren müssen, für die Ausnahmen ausgelöst werden, wenn Sie diesen Code zu sehen, wie Ausnahmen behandelt. Sie werden oft in eine "Was wäre wenn ..." Situation geraten und es kann sehr mühsam sein, einfach herauszufinden, ob Ausnahmen korrekt behandelt werden.

Re Werfen bedeutet, dass Code Ihre EJBs aufrufen wird kontrollieren Code übersät sein, die normalerweise nichts zu dem anrufenden Klasse bedeutet. n.b. Das Auslösen geprüfter Ausnahmen von EJB-Methoden bedeutet, dass Sie für das manuelle Zurücksetzen von Transaktionen verantwortlich sind.

0

Außer dem, was noch von @anthares beantwortet:

Denn wenn Sie Ausnahme fangen Sie sollen es richtig behandeln. Und Sie können nicht erwarten, alle Arten von Ausnahmen in Ihrem Code zu behandeln. Auch wenn Sie alle Ausnahmen abfangen, erhalten Sie möglicherweise eine Ausnahme, die nicht mit Code umgehen und verhindern kann, der im Stapel oben ist, um es ordnungsgemäß zu behandeln.

Der allgemeine Grundsatz ist, den spezifischsten Typ zu fangen, den Sie können.

catch(Exception) ist eine schlechte Übung, weil es alle RuntimeException (unchecked Ausnahme) auch abfängt.

0

Aber manchmal ist es in Ordnung! Wie wenn du einen Code hast, der etwas "Extra" macht, was dir wirklich egal ist, und du willst nicht, dass es deine Bewerbung sprengt. Ich habe zum Beispiel kürzlich an einer großen Anwendung gearbeitet, bei der unsere Geschäftspartner eine bestimmte tägliche Transaktion in einer neuen Protokolldatei zusammenfassen wollten. Sie erklärten, dass das Protokoll für sie nicht so wichtig war und dass es nicht als Voraussetzung galt. Es war nur etwas Extra, das ihnen helfen würde, die verarbeiteten Daten zu verstehen. Sie brauchten es nicht, weil sie die Informationen woanders bekommen konnten. Das ist ein seltener Fall, in dem es vollkommen in Ordnung ist, Ausnahmen zu fangen und zu schlucken.

Ich arbeitete auch in einer Firma, in der alle Throwables gefangen wurden, und dann innerhalb einer benutzerdefinierten RuntimeException erneut gestartet. Ich würde diesen Ansatz nicht empfehlen, sondern nur darauf hinweisen, dass es getan ist.

0

Ich finde zwei akzeptable Verwendungen von Catch (Exception): - Auf der obersten Ebene der Anwendung (kurz vor der Rückkehr zum Benutzer). Auf diese Weise können Sie eine angemessene Nachricht bereitstellen. - Verwenden Sie es, um Low-Level-Ausnahmen zu einem Business-Masken zu maskieren.

Der erste Fall ist selbsterklärende, aber lassen Sie mich die zweite Entwicklung:

tun:

try { 
    xxxx 
} catch(Exception e) { 
    logger.error("Error XXX",e) 
} 

ist Maskierung Fehler wie gesagt @dimitarvp.

Aber

try { 
    xxxx 
} catch(Exception e) { 
    throw new BussinessException("Error doing operation XXX",e) 
} 

Es ist eine andere Sache. Auf diese Weise ignorieren Sie nicht Bugs und verstecken sich unter dem Teppich. Sie bieten eine Ausnahme auf hoher Ebene mit einer aussagekräftigeren Nachricht für höhere Anwendungsschichten.

Es ist immer wichtig, auch zwei Ausnahmen auf der richtigen Ebene zu verwalten. Wenn Sie eine Low-Level-Exception in eine High-Business-Ebene eskalieren lassen, ist es praktisch unmöglich, dass die höhere Ebene sie gut verwaltet. In diesen Fällen bevorzuge ich es, die Ausnahmen auf niedriger Ebene mit einer Geschäftsmaske zu maskieren, die einen besseren Kontext und eine bessere Nachricht bietet und außerdem die ursprüngliche Ausnahme enthält, um zu den Details zu gelangen.

Trotzdem, wenn Sie konkretere Ausnahmen finden können und Sie eine bessere Behandlung für sie bieten können, müssen Sie es tun.

Wenn Sie in einem Codeblock eine SQLException und eine NetworkException abrufen können, müssen Sie sie abfangen und entsprechende Meldungen und Behandlung für jede von ihnen bereitstellen. Aber wenn am Ende des try/catch-Blocks eine Exception mit einer BussinessException verknüpft ist, ist es für mich in Ordnung. In der Tat finde ich angemessen, dass höhere Service-Schichten nur Business-Ausnahmen werfen (mit Details im Inneren).

Verwandte Themen