java - tabelle - jtable überschrift




Wann wählen Sie die aktivierten und deaktivierten Ausnahmen aus (12)

Wie entscheiden Sie in Java (oder einer anderen Sprache mit aktivierten Ausnahmen) beim Erstellen einer eigenen Ausnahmeklasse, ob sie aktiviert oder deaktiviert werden soll?

Mein Instinkt ist zu sagen, dass eine geprüfte Ausnahme in Fällen erforderlich wäre, in denen der Anrufer in der Lage sein könnte, sich produktiv zu erholen, wo eine unkontrollierte Ausnahme eher für nicht behebbare Fälle wäre, aber ich würde mich für die Gedanken anderer interessieren.


Die Regel, die ich verwende, lautet: Benutze niemals ungeprüfte Ausnahmen! (oder wenn du es nicht siehst)

Es gibt einen sehr starken Fall für das Gegenteil: Verwenden Sie niemals geprüfte Ausnahmen. Ich zögere, in der Debatte Partei zu ergreifen, aber es scheint einen breiten Konsens zu geben, dass die Einführung von geprüften Ausnahmen im Nachhinein eine falsche Entscheidung war. Bitte schießen Sie nicht den Boten und beziehen Sie sich auf those arguments .


Überprüfte Ausnahmen sind nützlich für behebbare Fälle, in denen Sie Informationen für den Aufrufer bereitstellen möchten (z. B. unzureichende Berechtigungen, Datei nicht gefunden usw.).

Ungeprüfte Ausnahmen werden, wenn überhaupt, nur selten verwendet, um den Benutzer oder Programmierer über schwerwiegende Fehler oder unerwartete Bedingungen während der Laufzeit zu informieren. Werfen Sie sie nicht aus, wenn Sie Code oder Bibliotheken schreiben, die von anderen verwendet werden, da sie möglicherweise nicht erwarten, dass Ihre Software ungeprüfte Ausnahmen auslöst, da der Compiler sie nicht dazu zwingt, abgefangen oder deklariert zu werden.


Die Regel, die ich verwende, lautet: Benutze niemals ungeprüfte Ausnahmen! (oder wenn du es nicht siehst)

Aus der Sicht des Entwicklers, der Ihre Bibliothek verwendet, oder des Endbenutzers, der Ihre Bibliothek / Anwendung verwendet, ist es wirklich nervig, mit einer Anwendung konfrontiert zu werden, die aufgrund einer unausgefüllten Ausnahme abstürzt. Und auf einen Catch-all zu zählen, ist auch nicht gut.

Auf diese Weise kann dem Endbenutzer immer noch eine Fehlermeldung angezeigt werden, anstatt dass die Anwendung vollständig verschwindet.


Du hast Recht.

Ungeprüfte Ausnahmen werden verwendet, um das System schnell ausfallen zu lassen, was eine gute Sache ist. Sie sollten klar angeben, was Ihre Methode erwartet, um richtig zu funktionieren. Auf diese Weise können Sie die Eingabe nur einmal validieren.

Zum Beispiel:

/**
 * @params operation - The operation to execute.
 * @throws IllegalArgumentException if the operation is "exit"
 */
 public final void execute( String operation ) {
     if( "exit".equals(operation)){
          throw new IllegalArgumentException("I told you not to...");
     }
     this.operation = operation; 
     .....  
 }
 private void secretCode(){
      // we perform the operation.
      // at this point the opreation was validated already.
      // so we don't worry that operation is "exit"
      .....  
 }

Nur um ein Beispiel zu geben. Der Punkt ist, wenn das System schnell ausfällt, dann wissen Sie, wo und warum es fehlgeschlagen ist. Sie erhalten einen Stacktrace wie:

 IllegalArgumentException: I told you not to use "exit" 
 at some.package.AClass.execute(Aclass.java:5)
 at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
 ar ......

Und du wirst wissen, was passiert ist. Die OtherClass in der Methode "delegateTheWork" (in Zeile 4569) hat Ihre Klasse mit dem Wert "exit" aufgerufen, auch wenn dies nicht der Fall sein sollte.

Andernfalls müssten Sie Ihren gesamten Code mit Validierungen versehen und das ist fehleranfällig. Außerdem ist es manchmal schwierig zu verfolgen, was schief gelaufen ist, und Sie können stundenlanges frustrierendes Debugging erwarten

Das Gleiche passiert mit NullPointerExceptions. Wenn Sie eine 700-Zeilen-Klasse mit 15 Methoden haben, die 30 Attribute verwendet und keine davon null sein kann, können Sie diese Attribute in den Konstruktoren oder validieren, anstatt sie in jeder dieser Methoden auf Nullwert zu prüfen Fabrikmethode.

 public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ 
      if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }

  }


  // the rest of the methods don't validate data1 anymore.
  public void method1(){ // don't worry, nothing is null 
      ....
  }
  public void method2(){ // don't worry, nothing is null 
      ....
  }
  public void method3(){ // don't worry, nothing is null 
      ....
  }

Überprüfte Ausnahmen Sind hilfreich, wenn der Programmierer (Sie oder Ihre Mitarbeiter) alles richtig gemacht, die Eingabe validiert, Tests durchgeführt und der gesamte Code fehlerfrei ist, der Code jedoch mit einem Webdienst eines Drittanbieters verbunden ist, der nicht erreichbar ist (oder eine Datei) Sie wurden von einem anderen externen Prozess usw. gelöscht). Der Webservice kann sogar validiert werden, bevor die Verbindung versucht wird, aber während der Datenübertragung ist etwas schief gelaufen.

In diesem Szenario gibt es nichts, was Sie oder Ihre Kollegen tun können, um ihm zu helfen. Aber immer noch müssen Sie etwas tun und lassen Sie die Anwendung nicht einfach in den Augen des Benutzers sterben und verschwinden. Sie verwenden eine geprüfte Ausnahme dafür und behandeln die Ausnahme, was können Sie tun, wenn das passiert ?, die meiste Zeit, nur um zu versuchen, den Fehler zu protokollieren, speichern Sie wahrscheinlich Ihre Arbeit (die App Arbeit) und eine Nachricht an den Benutzer . (Die Seite blabla ist unten, bitte versuchen Sie es später erneut usw.)

Wenn die geprüfte Ausnahme überstrapaziert wird (durch das Hinzufügen der Ausnahme "Auslösen" in allen Methoden-Signaturen), wird Ihr Code sehr fragil, da jeder diese Ausnahme ignoriert (weil er zu allgemein ist) und die Qualität des Codes ernsthaft ist kompromittiert.

Wenn Sie die ungeprüfte Ausnahme übermäßig verwenden, wird Ähnliches passieren. Die Benutzer dieses Codes wissen nicht, ob etwas schiefgehen kann und es wird eine Menge von {...} catch (Throwable t) angezeigt.


Geprüfte Ausnahmen sind großartig, solange Sie verstehen, wann sie verwendet werden sollten. Die Java-Core-API folgt diesen Regeln für SQLException (und manchmal für IOException) nicht, weshalb sie so schrecklich sind.

Überprüfte Ausnahmen sollten für vorhersehbare , aber nicht durchführbare Fehler verwendet werden, von denen eine Wiederherstellung sinnvoll ist .

Ungeprüfte Ausnahmen sollten für alles andere verwendet werden.

Ich werde das für Sie aufschlüsseln, weil die meisten Leute nicht verstehen, was das bedeutet.

  1. Vorhersehbar, aber nicht verhindernd : Der Aufrufer hat alles in seiner Macht Stehende getan, um die Eingabeparameter zu validieren, aber eine Bedingung außerhalb ihrer Kontrolle hat dazu geführt, dass die Operation fehlgeschlagen ist. Beispielsweise versuchen Sie eine Datei zu lesen, aber jemand löscht sie zwischen dem Zeitpunkt, an dem Sie überprüfen, ob es existiert, und dem Zeitpunkt, an dem die Leseoperation beginnt. Wenn Sie eine geprüfte Ausnahme deklarieren, weisen Sie den Aufrufer an, diesen Fehler vorherzusehen.
  2. Wiederherstellen von : Es hat keinen Sinn, Anrufern mitzuteilen, dass sie Ausnahmen erwarten, von denen sie nicht wiederherstellen können. Wenn ein Benutzer versucht, aus einer nicht vorhandenen Datei zu lesen, kann der Aufrufer sie nach einem neuen Dateinamen fragen. Wenn die Methode andererseits aufgrund eines Programmierfehlers fehlschlägt (ungültige Methodenargumente oder fehlerhafte Methodenimplementierung), kann die Anwendung nichts unternehmen, um das Problem mitten in der Ausführung zu beheben. Das Beste, was es tun kann, ist, das Problem zu protokollieren und darauf zu warten, dass der Entwickler es zu einem späteren Zeitpunkt repariert.

Wenn die Ausnahme, die Sie werfen, alle oben genannten Bedingungen erfüllt, sollte sie eine ungeprüfte Ausnahme verwenden.

Neubewertung auf jeder Ebene : Manchmal ist die Methode, die die geprüfte Ausnahme abfängt, nicht der richtige Ort, um den Fehler zu behandeln. In diesem Fall überlegen Sie, was für Ihre eigenen Anrufer angemessen ist. Wenn die Ausnahmebedingung vorhersehbar, nicht durchführbar und zum Wiederherstellen sinnvoll ist, sollten Sie selbst eine geprüfte Ausnahme auslösen. Wenn nicht, sollten Sie die Ausnahme in eine ungeprüfte Ausnahme umbrechen. Wenn Sie dieser Regel folgen, werden Sie je nach Layer, in dem Sie sich befinden, geprüfte Ausnahmen in ungeprüfte Ausnahmen umwandeln und umgekehrt.

Verwenden Sie für die geprüften und nicht aktivierten Ausnahmen die richtige Abstraktionsebene . Zum Beispiel sollte ein Code-Repository mit zwei verschiedenen Implementierungen (Datenbank und Dateisystem) vermeiden, implementierungsspezifische Details SQLException IOException indem SQLException oder IOException . Stattdessen sollte die Ausnahme in eine Abstraktion eingebettet werden, die alle Implementierungen umfasst (z. B. RepositoryException ).


Hier ist eine sehr einfache Lösung für Ihr Checked / Ungeprüft-Dilemma.

Regel 1: Stellen Sie sich eine ungeprüfte Ausnahme als testbare Bedingung vor, bevor der Code ausgeführt wird. beispielsweise…

x.doSomething(); // the code throws a NullPointerException

wo x ist null ... ... sollte der Code möglicherweise folgende haben ...

if (x==null)
{
    //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
    x = new X();
}
x.doSomething();

Regel 2: Stellen Sie sich eine geprüfte Ausnahme als nicht testbare Bedingung vor, die bei der Ausführung des Codes auftreten kann.

Socket s = new Socket(“google.com”, 80);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

... im obigen Beispiel ist die URL (google.com) möglicherweise nicht verfügbar, da der DNS-Server ausgefallen ist. Selbst in dem Moment, in dem der DNS-Server funktionierte und den 'google.com'-Namen in eine IP-Adresse auflöste, konnte das Netzwerk bei einer Verbindung zu google.com jederzeit abstürzen. Sie können das Netzwerk nicht immer testen, bevor Sie Streams lesen und schreiben.

Es gibt Zeiten, in denen der Code einfach ausgeführt werden muss, bevor wir wissen, ob ein Problem vorliegt. Indem Entwickler dazu gezwungen werden, ihren Code so zu schreiben, dass sie diese Situationen mit Checked Exception umgehen müssen, muss ich meinen Hut vor dem Schöpfer von Java legen, der dieses Konzept erfunden hat.

Im Allgemeinen folgen fast alle APIs in Java den obigen 2 Regeln. Wenn Sie versuchen, in eine Datei zu schreiben, könnte sich die Festplatte füllen, bevor Sie den Schreibvorgang abgeschlossen haben. Es ist möglich, dass andere Prozesse dazu führten, dass die Festplatte voll wurde. Es gibt einfach keine Möglichkeit, diese Situation zu testen. Für diejenigen, die mit Hardware interagieren, wo zu irgendeinem Zeitpunkt die Verwendung der Hardware fehlschlagen kann, scheinen die Überprüfungsausnahmen eine elegante Lösung für dieses Problem zu sein.

Da ist eine Grauzone. Für den Fall, dass viele Tests benötigt werden (eine überwältigende if-Anweisung mit vielen && und ||), ist die Ausnahme eine CheckedException, einfach weil es zu viel Schmerz ist, um richtig zu kommen - Sie können dieses Problem einfach nicht sagen ist ein Programmierfehler. Wenn es viel weniger als 10 Tests gibt (zB 'if (x == null)'), sollte der Programmierfehler eine UncheckedException sein.

Im Umgang mit Sprachdolmetschern wird es interessant. Sollte nach den obigen Regeln ein Syntaxfehler als eine geprüfte oder ungeprüfte Ausnahme betrachtet werden? Ich würde argumentieren, dass, wenn die Syntax der Sprache getestet werden kann, bevor es ausgeführt wird, sollte es eine UncheckedException sein. Wenn die Sprache nicht getestet werden kann - ähnlich wie Assemblercode auf einem PC ausgeführt wird, sollte der Syntaxfehler eine geprüfte Ausnahme sein.

Die obigen 2 Regeln werden wahrscheinlich 90% Ihrer Bedenken beseitigen, aus denen Sie wählen können. Um die Regeln zusammenzufassen, folgen Sie diesem Muster ... 1) Wenn der auszuführende Code getestet werden kann, bevor er ausgeführt wird, damit er korrekt ausgeführt wird und eine Ausnahme auftritt - aka ein Programmierfehler, sollte die Ausnahme eine UncheckedException (eine Unterklasse von RuntimeException) sein ). 2) Wenn der auszuführende Code nicht getestet werden kann, bevor er ausgeführt wird, damit er ordnungsgemäß ausgeführt wird, sollte die Ausnahme eine geprüfte Ausnahme (eine Unterklasse der Ausnahme) sein.


Hier möchte ich meine Meinung teilen, die ich nach vielen Jahren Entwicklungserfahrung habe:

  1. Überprüfte Ausnahme Dies ist ein Teil des Geschäftsanwendungsfalls oder des Anrufverlaufs. Dies ist ein Teil der Anwendungslogik, die wir erwarten oder nicht erwarten. Zum Beispiel Verbindung abgelehnt, Bedingung ist nicht erfüllt etc. Wir müssen damit umgehen und zeigen entsprechende Nachricht an den Benutzer mit Anweisungen, was passiert ist und was als nächstes (versuchen Sie es später usw.). Ich nenne es normalerweise Post-Processing-Ausnahme oder "Benutzer" Ausnahme.

  2. Ungeprüfte Ausnahme Dies ist ein Teil der Programmier-Ausnahme, ein Fehler in der Software-Code-Programmierung (Bug, Defekt) und spiegelt eine Art und Weise wider, wie Programmierer API gemäß Dokumentation verwenden müssen. Wenn ein externes lib / framework-Dokument angibt, dass Daten in einem bestimmten Bereich und nicht null erwartet werden, weil NPE oder IllegalArgumentException ausgelöst werden, sollte der Programmierer dies erwarten und die API entsprechend der Dokumentation korrekt verwenden. Andernfalls wird die Ausnahme ausgelöst. Ich nenne es normalerweise Vorverarbeitung Ausnahme oder "Validierung" Ausnahme.

Nach Zielgruppe. Sprechen wir nun über Zielgruppe oder Gruppe von Personen, für die die Ausnahmen entworfen wurden (meiner Meinung nach):

  1. Überprüfte Ausnahme Zielgruppe sind Benutzer / Kunden.
  2. Ungeprüfte Ausnahme Zielgruppe sind Entwickler. Mit anderen Worten, ungeprüfte Ausnahmen sind nur für Entwickler gedacht.

Nach Anwendungsentwicklung Lebenszyklusphase.

  1. Die geprüfte Ausnahme ist so konzipiert, dass sie während des gesamten Produktionslebenszyklus als normaler und erwarteter Mechanismus existiert, mit dem eine Anwendung Ausnahmefälle behandelt.
  2. Eine ungeprüfte Ausnahme ist nur während des Anwendungsentwicklungs- / Testlebenszyklus vorgesehen. Alle sollten während dieser Zeit behoben werden und sollten nicht ausgelöst werden, wenn eine Anwendung bereits in der Produktion ausgeführt wird.

Der Grund, warum Frameworks normalerweise unchecked Exceptions (Spring zum Beispiel) verwenden, ist, dass Framework die Geschäftslogik Ihrer Anwendung nicht bestimmen kann. Das liegt an den Entwicklern, diese zu fangen und eigene Logik zu entwickeln.


Ich denke, wenn Application Exception deklariert wird, sollte es unchecked Exception sein, dh Unterklasse von RuntimeException. Der Grund ist, dass Anwendungscode nicht mit try-catch durcheinandergebracht wird und eine Deklaration der Methode ausgelöst wird. Wenn Ihre Anwendung Java API verwendet, die geprüfte Ausnahmen auslöst, die sowieso behandelt werden müssen. In anderen Fällen kann die Anwendung eine ungeprüfte Ausnahme auslösen. Wenn der Anwendungsaufrufer weiterhin die ungeprüfte Ausnahme behandeln muss, kann dies geschehen.


In der Regel stimme ich der Einstellung für ungeprüfte Ausnahmen zu, insbesondere beim Entwerfen einer API. Der Aufrufer kann immer wählen, eine dokumentierte, ungeprüfte Ausnahme abzufangen. Sie zwingen den Anrufer nicht unnötig dazu.

Ich finde überprüfte Ausnahmen auf der unteren Ebene als Implementierungsdetails nützlich. Es scheint oft ein besserer Kontrollmechanismus zu sein, als einen spezifizierten Fehler "Rückkehrcode" zu verwalten. Es kann manchmal helfen, die Auswirkung einer Idee auf eine Codeänderung auf niedriger Ebene zu sehen ... eine geprüfte Ausnahme stromabwärts zu deklarieren und zu sehen, wer angepasst werden muss. Dieser letzte Punkt trifft nicht zu, wenn es viele generische gibt: catch (Exception e) oder throws Exception, die sowieso nicht so gut durchdacht sind.


Sie können es eine überprüfte oder ungeprüfte Ausnahme nennen; Beide Ausnahmearten können jedoch vom Programmierer abgefangen werden. Daher lautet die beste Antwort: Schreiben Sie alle Ausnahmen als nicht aktiviert und dokumentieren Sie sie. Auf diese Weise kann der Entwickler, der Ihre API verwendet, wählen, ob er diese Ausnahme abfangen und etwas unternehmen möchte. Überprüfte Ausnahmen sind eine völlige Verschwendung aller Zeiten und es macht Ihren Code zu einem schockierenden Albtraum. Der richtige Komponententest bringt dann alle Ausnahmen zum Vorschein, mit denen Sie möglicherweise etwas anfangen müssen.


Wenn eine Ausnahme mit geringerer Wahrscheinlichkeit erwartet wird und wir selbst dann fortfahren können, nachdem wir sie eingefangen haben, und wir nichts tun können, um diese Ausnahme zu vermeiden, können wir die geprüfte Ausnahme verwenden.

Wann immer wir etwas Sinnvolles tun wollen, wenn eine bestimmte Ausnahme auftritt und wenn diese Ausnahme erwartet, aber nicht sicher ist, können wir die geprüfte Ausnahme verwenden.

Wenn Exception in verschiedenen Layern navigiert, müssen wir sie nicht in jedem Layer abfangen. In diesem Fall können wir Runtime-Exception oder Wrapp-Exception als unchecked Ausnahme verwenden.

Eine Laufzeitausnahmebedingung wird verwendet, wenn die Ausnahme am wahrscheinlichsten auftritt, es gibt keine Möglichkeit, weiter zu gehen, und nichts kann wiederhergestellt werden. In diesem Fall können wir Vorkehrungen in Bezug auf diese Ausnahme treffen. EX: NUllPointerException, ArrayOutofBoundsException. Diese werden eher passieren. In diesem Szenario können wir beim Codieren Vorkehrungen treffen, um eine solche Ausnahme zu vermeiden. Sonst müssen wir versuchen, Catch-Blöcke überall zu schreiben.

Allgemeinere Ausnahmen können gemacht werden. Nicht geprüft, weniger allgemein werden geprüft.


Überprüfte Ausnahme: Wenn der Client eine Ausnahme wiederherstellen kann und fortfahren möchte, verwenden Sie die geprüfte Ausnahme.

Unchecked Exception: Wenn ein Client nach der Ausnahme keine weiteren Aktionen ausführen kann, wird die ungeprüfte Ausnahme ausgelöst.

Beispiel: Wenn Sie eine arithmetische Operation in einer Methode A () und basierend auf der Ausgabe von A () erwarten, müssen Sie eine andere Operation ausführen. Wenn die Ausgabe von der Methode A (), die Sie während der Laufzeit nicht erwarten, null ist, wird erwartet, dass Sie den Null-Zeiger Exception auslösen, der eine Laufzeitausnahme darstellt.

Siehe here





checked-exceptions