2009-10-16 2 views
6

Ich habe ein coding Standards Treffen in etwas in einer Stunde und ich brauche eine schnelle Antwort zu diesem.Benötigen Sie maßgebliche Quelle für, warum Sie java.lang.Exception nicht werfen oder fangen sollten

Allgemeinwissen unter erfahrenen Java-Programmierern ist, dass Sie java.lang.Exception nicht werfen oder fangen (mit seltenen Ausnahmen - kein Wortspiel beabsichtigt). Der Grund, warum Sie dies nicht tun, ist, dass die Aussage

catch (java.lang.Exception ex) {...} 

wird auch nicht markiert Ausnahmen fangen, und in den meisten Fällen ist dies nicht das, was beabsichtigt ist.

Wir haben bereits eine Menge Legacy-Code von bestehenden Teammitgliedern geschrieben, in dem sie eine Unterklasse von java.lang.Exception abfangen, einen Fehler protokollieren und die Unterklasse als java.lang.Exception erneut auslösen.

Ich brauche sie davon zu überzeugen, dass

  1. Sie brauchen, so zu stoppen Code zu schreiben.
  2. bestehende Code, der dieses anti-Muster verwendet muss

Nummer 2 bedeutet einen fairen Betrag von Refactoring fixiert werden.

Es wird das Argument auf der Sitzung verkürzen, wenn ich einen Artikel oder einen Blog-Eintrag von einem der Java-Community-Schwergewichte zeigen kann, die diesen Punkt (d. H. Joshua Bloch, James Gosling) macht. Mein Google-Fu hat bisher noch nichts gefunden.

Kennt jemand einen Artikel oder Blog von einem respektierten Java-Guru, der besagt, dass Sie java.lang.Exception nicht werfen oder fangen sollten?

Schnelle Antworten werden sehr geschätzt.

Dean

+1

nur wollen Sie diese Frage zeigen: http://stackoverflow.com/questions/237585/java-lang-exception-vs-rolling-your-own-exception einige nette Antworten in es – bastianneu

+0

I lies das vor dem Posten. Ein paar Antworten und Kommentare sagen dasselbe, aber ich suche nach einer Autorität. Dies wird zu einer gewissen Menge an Refactoring führen, so dass es hilfreich wäre, die Meinung eines Experten zu haben, um mich zu unterstützen. –

Antwort

0

Ich denke, der Punkt, dass, wenn Sie nicht wissen, wie eine spezifische Ausnahme zu behandeln, dann sollten Sie es nicht fangen. Es sollte sich auf ein höheres Niveau ausbreiten in der Hoffnung, dass es wissen könnte, was damit zu tun ist. Wenn Ausnahmen zu früh eingefangen werden, führt dies dazu, dass Ausnahmen stillschweigend verschluckt werden und es unmöglich wird, mit ihnen außer der Protokollierung etwas Nützliches zu tun.

Stellen Sie sich vor, was passieren würde, wenn der Konstruktor FileInputStream eine Ausnahme intern protokolliert, wenn Sie versucht haben, eine Datei zu öffnen, die nicht existiert, aber diesen Fehler nicht Ihrem Code angezeigt hat. Es ist in Ordnung, dass der Fehler protokolliert wird, aber Ihr Code möchte diese Ausnahme abfangen und etwas Nützliches damit machen (zB den Benutzer nach einem neuen Dateinamen fragen). Wenn sie zu catch (Exception) wären, könnten Sie das nicht tun.

0

Wenn Sie eine Kopie von Josh Blochs Effektivem Java zur Hand haben, weiß ich, dass er die Ausnahmebehandlung in einem guten Detail behandelt. Ich habe momentan keinen Zugriff darauf, also kann ich es nicht zusammenfassen oder dir Seitenverweise geben, aber ich bin mir ziemlich sicher, dass er gute Argumente dafür hat, java.lang.Exception nicht zu fangen.

+1

Das wäre Kapitel 9 (17 Seiten). Er zieht keines von beiden vor, betont jedoch, dass Sie nur geprüfte Ausnahmen verwenden sollten, wenn der Anrufer etwas gegen das Problem unternehmen kann. So ist OOM ein RuntimeExc., Während NoMoreElements ein (schlechtes) checked exc ist. –

3

Hier gibt es keine Gemeinsamkeiten.Sie werden zwei Gruppen finden:

  1. Diejenigen, die überprüft Ausnahmen hassen sie in einem RuntimeException irgendeiner Art fangen und wickeln.

  2. Diejenigen, die RuntimeException

Die erste Gruppe Hass hasst ihren Code mit try...catch zu durchlöchern, zumal in den meisten Fällen können Sie die Ausnahme nicht behandeln, wenn Sie es zuerst sehen. Think IOException: Es könnte für jedes Byte, das Sie lesen, geworfen werden. Was ist der Low-Level-Code dafür? Es muss neu gestartet werden, damit jemand, der höher ist, dem Fehler einen nützlichen Kontext hinzufügen kann (wie die Datei, die Sie gerade gelesen haben).

Die andere Gruppe möchte sehen, was schief gehen könnte. RuntimeException verbirgt dies effektiv.

Es gibt eine einfache Lösung, BTW: Machen Sie Ausnahme RuntimException zu verlängern. Wahnsinnig? Nicht wirklich. Wenn Sie das mit JDK 7 tun, erhalten Sie zwei Kompilierungsfehler.

Der nächste Schritt wäre, alle Java-Compiler alle Laufzeitausnahmen aufzulisten und sie im Eintrag throws in der Klassendatei aufzulisten. Du musst sie immer noch nicht fangen, aber jetzt wirst du wissen, welche passieren könnten.

Zuletzt erweitern Sie die IDEs, um dies anzuzeigen. Und presto, beide Gruppen könnten glücklich sein. Leider wird dies nicht passieren.

+0

Ein bisschen weitschweifig, aber ich mag es! –

+0

Personen, die geprüfte Ausnahmen mögen, hassen keine Laufzeitausnahmen, sondern beschränken ihre Verwendung auf die Situationen, in denen sie angemessen sind. – Brian

+0

@Brian: Mein Argument ist, dass es keine Möglichkeit gibt, zuzustimmen, wann sie "angemessen" sind. 'SQLException' und' IOException' sind aus meiner Sicht eindeutig Laufzeitausnahmen, da sie meiner Erfahrung nach häufiger wegen eines Programmierfehlers ausgelöst werden und nicht aufgrund einer Bedingung, die der Aufrufer tatsächlich verarbeiten könnte. –

5

Siehe this article von Brian Goetz (der Concurrency-Assistenten), der auch unter Angabe Josh Bloch in Effective Java

2

wo sie fangen eine Unterklasse von java.lang.Exception, melden Sie einen Fehler seine eigene Einsicht hat, und erneut die Unterklasse als java.lang.Exception. Ich muss sie davon überzeugen, dass sie aufhören müssen, Code wie diesen zu schreiben.

Ich stimme zu, sie sollten eine andere Taktik verwenden, aber aus verschiedenen Gründen. Es ist nicht sehr sinnvoll, eine Ausnahme zu erfassen, nur um sie zu protokollieren und erneut auszulösen.

Eine Alternative ist: fangen Sie nicht die Ausnahme und lassen Sie etwas höheren Code (wie ein Java-EE-Filter oder versuchen/fangen in Ihrer main() -Methode) fangen und protokollieren alle nicht abgefangenen Ausnahmen. Dann stellen Sie sicher, dass jede Ausnahme nur einmal protokolliert wird, und Sie wissen, dass alle nicht abgefangenen Ausnahmen protokolliert werden.

Wenn Sie der Ausnahme zusätzliche Informationen hinzufügen müssen, fangen Sie sie ab, ändern Sie die Nachricht und wiederholen Sie sie.Normalerweise verwende ich eine Runtime dafür:

} catch (Exception originalException) { 
    throw new RuntimeException("user name was " + userName, originalException); 
} 
+0

Ausnahmen sollten so nah wie möglich an der Stelle protokolliert werden, an die sie geworfen wurden. Es ist möglich, dass irgendwo vor der Exception die Exception verschluckt wird oder ein anderer Fehler oder RuntimeException (z. B. NullPointerException) auftritt, der die Upstream-Protokollierung verhindert. Meinten Sie für Ihre catch() -Anweisung oben, RuntimeException auch zu fangen? –

+0

@Dean Schulze vermutlich, wenn eine Ausnahme verschluckt wurde, bedeutet das, dass es keine unerwartete Ausnahme war, aber es war eine erwartete und der Code wusste, wie man programmatisch damit umgeht. Anders ausgedrückt: Wer die Ausnahme behandelt, sollte sie protokollieren. Wenn es nicht behandelt wird, sollten Sie einen Mechanismus für die Behandlung und Protokollierung dieser unerwarteten Ausnahmen haben. Dadurch wird sichergestellt, dass die Stapelverfolgung nur einmal in den Protokollen angezeigt wird. –

+0

@Dean Schulze wie die Catch-Anweisung abfangen Exception, yeah, ich habe versucht zu zeigen, dass Sie nicht den Fehler protokollieren müssen und Variablenwerte protokollieren, wenn die Ausnahme abgefangen wird. Stattdessen können Sie die Ausnahme abfangen und diese Werte zur Nachricht hinzufügen, dann die Ausnahme umbrechen und erneut auslösen. Ihre zusätzlichen Daten werden weiterhin in den Protokollen gespeichert (und der Stack-Trace wird nur einmal ausgegeben, wodurch das Durchsuchen der Protokolle nach Fehlern erleichtert wird). –

1

es ist ein langer Artikel aber this bietet Ihnen:

  1. Verwendung Ausnahmen überprüft, wenn der Kunde dieser Fehler erwartet regelmäßig auftreten und damit umgehen müssen (ex: user DB-Server ging)

In der Theorie # 1 (exp: -entered Daten nicht Validierung)

  • Verwendung ungeprüfte Ausnahmen für unerwartete Bedingungen (ex passieren Fehler() sollten ihren eigenen Ausnahmetyp haben, und der einzige Ort, der eine # 2 (eine RuntimeException) abfangen sollte, ist eine Art von Top-Level-Handler, der die Ausnahme abfängt, sie protokolliert und dem Benutzer eine Fehlermeldung anzeigt Hier sollten Sie wahrscheinlich Throwable abfangen, um sicherzustellen, dass alle nicht abgefangenen Ausnahmen behandelt werden.

    Nach diesen Richtlinien sollten Sie keine Exception abfangen, da sie keines der obigen Kriterien erfüllt (was bedeutet, dass es sich nicht um eine RuntimeException handelt und keine spezialisierte Exception-Sublcase zur Angabe eines erwarteten Fehlers ist).

  • +1

    Die URL zu dem Artikel, auf den verwiesen wird, hat sich geändert (http://www.oracle.com/technetwork/articles/entarch/effective-exceptions-092345.html). @TerrelShumway hat den gleichen Artikel in seiner Antwort gepostet. – hotshot309

    +0

    @ hotshot309 behoben. Vielen Dank! –

    +0

    Menschen, die geprüfte Ausnahmen mögen, hassen Laufzeitausnahmen nicht, sie beschränken ihre Verwendung nur auf die Situationen, in denen sie angemessen sind. – Brian

    1

    Hier ist eine sehr insightful article

    Zusammenfassung:

    1. Verwenden geprüfte Ausnahmen für seltene, aber gültig Eventualitäten, die den Zweck des Codes beziehen. Client-Code sollte wissen, wie man damit umgeht.

    2. Verwenden Sie ungeprüfte Ausnahmen für Fehler, die nicht passieren sollten, aber tun. (Server down, Klassenpfad falsch konfiguriert, SQL-Syntaxfehler usw.) Der IT-Typ, der den Server verwaltet, oder der Entwickler, der einfach bad preparedStatement() übergeben hat, sollte wissen, wie er diese Probleme beheben kann. Fehler sollten sich bis zur Protokollierungsschicht ausbreiten, damit die Informationen nicht verloren gehen.

    Verwandte Themen