Frage

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

Mein Instinkt sagt mir, dass eine geprüfte Ausnahme in Fällen erforderlich wäre, in denen der Aufrufer möglicherweise auf produktive Weise wiederhergestellt werden könnte, wohingegen eine ungeprüfte Ausnahme eher für nicht behebbare Fälle geeignet wäre, aber ich wäre an den Gedanken anderer interessiert.

War es hilfreich?

Lösung

Geprüfte Ausnahmen sind großartig, solange Sie wissen, wann sie verwendet werden sollten.Die Java-Kern-API befolgt diese Regeln für SQLException (und manchmal auch für IOException) nicht, weshalb sie so schrecklich sind.

Geprüfte Ausnahmen verwendet werden soll vorhersagbar, Aber unvermeidbar Fehler, die sind vernünftig, sich davon zu erholen.

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

Ich werde das für Sie aufschlüsseln, da die meisten Menschen falsch verstehen, was das bedeutet.

  1. Vorhersehbar, aber nicht vermeidbar:Der Aufrufer hat alles in seiner Macht Stehende getan, um die Eingabeparameter zu validieren, aber eine Bedingung, die außerhalb seiner Kontrolle liegt, hat dazu geführt, dass der Vorgang fehlgeschlagen ist.Sie versuchen beispielsweise, eine Datei zu lesen, aber jemand löscht sie zwischen dem Zeitpunkt, an dem Sie überprüfen, ob sie vorhanden ist, und dem Zeitpunkt, an dem der Lesevorgang beginnt.Indem Sie eine aktivierte Ausnahme deklarieren, weisen Sie den Aufrufer an, mit diesem Fehler zu rechnen.
  2. Angemessen, sich davon zu erholen:Es macht keinen Sinn, Anrufern zu sagen, dass sie Ausnahmen erwarten sollen, von denen sie sich nicht erholen können.Wenn ein Benutzer versucht, aus einer nicht vorhandenen Datei zu lesen, kann der Aufrufer ihn zur Eingabe eines neuen Dateinamens auffordern.Wenn die Methode andererseits aufgrund eines Programmierfehlers (ungültige Methodenargumente oder fehlerhafte Methodenimplementierung) fehlschlägt, kann die Anwendung nichts tun, 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 behebt.

Es sei denn, die Ausnahme, die Sie auslösen, trifft zu alle Unter den oben genannten Bedingungen sollte eine ungeprüfte Ausnahme verwendet werden.

Bewerten Sie auf jeder Ebene neu:Manchmal ist die Methode, die die geprüfte Ausnahme abfängt, nicht der richtige Ort, um den Fehler zu behandeln.Überlegen Sie in diesem Fall, was für Ihre eigenen Anrufer sinnvoll ist.Wenn die Ausnahme vorhersehbar und unvermeidbar ist und eine Wiederherstellung sinnvoll ist, sollten Sie selbst eine aktivierte Ausnahme auslösen.Wenn nicht, sollten Sie die Ausnahme in eine ungeprüfte Ausnahme einschließen.Wenn Sie diese Regel befolgen, werden Sie abhängig von der Ebene, in der Sie sich befinden, aktivierte Ausnahmen in ungeprüfte Ausnahmen umwandeln und umgekehrt.

Für aktivierte und nicht aktivierte Ausnahmen gilt: Verwenden Sie die richtige Abstraktionsebene.Beispielsweise sollte ein Code-Repository mit zwei unterschiedlichen Implementierungen (Datenbank und Dateisystem) vermeiden, durch Auslösen implementierte spezifische Details offenzulegen SQLException oder IOException.Stattdessen sollte die Ausnahme in eine Abstraktion eingeschlossen werden, die alle Implementierungen umfasst (z. B. RepositoryException).

Andere Tipps

Aus Ein Java-Lernender:

Wenn eine Ausnahme eintritt, müssen Sie die Ausnahme entweder fangen und verarbeiten oder den Compiler mitteilen, dass Sie sie nicht erledigen können, indem Sie erklären, dass Ihre Methode diese Ausnahme ausgelöst hat. Der Code, der Ihre Methode verwendet Kann auch erklären, dass sie die Ausnahme ausführt, wenn sie nicht damit umgehen kann).

Der Compiler prüft, dass wir eines der beiden Dinge getan haben (fangen oder deklarieren).Diese werden also überprüfte Ausnahmen genannt.Fehler und Laufzeitausnahmen werden jedoch nicht vom Compiler überprüft (obwohl Sie sich dafür entscheiden können, zu fangen oder zu deklarieren, ist dies nicht erforderlich).Diese beiden werden also als nicht überprüfte Ausnahmen bezeichnet.

Fehler werden verwendet, um die Bedingungen darzustellen, die außerhalb der Anwendung auftreten, wie z. B. Absturz des Systems.Die Laufzeitausnahmen erfolgen normalerweise durch Fehler in der Anwendungslogik.Sie können in diesen Situationen nichts tun.Wenn eine Laufzeitausnahme auftritt, müssen Sie Ihren Programmcode neu schreiben.Diese werden also nicht vom Compiler überprüft.Diese Laufzeitausnahmen werden in der Entwicklung und in der Testzeit aufdecken.Dann müssen wir unseren Code neu umrüsten, um diese Fehler zu entfernen.

Die Regel, die ich verwende, ist:Verwenden Sie niemals ungeprüfte Ausnahmen!(Oder wenn Sie keinen Ausweg mehr sehen)

Es gibt sehr starke Argumente für das Gegenteil:Verwenden Sie niemals geprüfte Ausnahmen.Ich zögere, in der Debatte Partei zu ergreifen, aber es scheint ein breiter Konsens darüber zu bestehen, dass die Einführung geprüfter Ausnahmen im Nachhinein eine falsche Entscheidung war.Bitte erschießen Sie nicht den Boten und verweisen Sie darauf diese Argumente.

Auf einem ausreichend großen System mit vielen Schichten sind geprüfte Ausnahmen nutzlos, da Sie ohnehin eine Strategie auf Architekturebene benötigen, um zu handhaben, wie die Ausnahme behandelt wird (verwenden Sie eine Fehlerbarriere).

Mit aktivierten Ausnahmen ist Ihre Fehlerbehandlungsstrategie mikroverwaltet und auf keinem großen System erträglich.

Meistens wissen Sie nicht, ob ein Fehler „behebbar“ ist, weil Sie nicht wissen, in welcher Schicht sich der Aufrufer Ihrer API befindet.

Nehmen wir an, ich erstelle eine StringToInt-API, die die String-Darstellung einer Ganzzahl in einen Int konvertiert.Muss ich eine geprüfte Ausnahme auslösen, wenn die API mit der Zeichenfolge „foo“ aufgerufen wird?Ist es wiederherstellbar?Ich weiß es nicht, da der Aufrufer meiner StringToInt-API in seiner Ebene die Eingabe möglicherweise bereits validiert hat. Wenn diese Ausnahme ausgelöst wird, handelt es sich entweder um einen Fehler oder eine Datenbeschädigung, die für diese Ebene nicht wiederhergestellt werden kann.

In diesem Fall möchte der Aufrufer der API die Ausnahme nicht abfangen.Er will die Ausnahme nur „aufsprudeln“ lassen.Wenn ich eine aktivierte Ausnahme wähle, verfügt dieser Aufrufer über viele nutzlose Catch-Blöcke, nur um die Ausnahme künstlich erneut auszulösen.

Was wiederherstellbar ist, hängt in den meisten Fällen vom Aufrufer der API ab, nicht vom Autor der API.Eine API sollte keine geprüften Ausnahmen verwenden, da nur ungeprüfte Ausnahmen die Wahl ermöglichen, eine Ausnahme entweder abzufangen oder zu ignorieren.

Du hast Recht.

Ungeprüfte Ausnahmen werden verwendet, um das System zu vermieten scheitern schnell Das ist eine gute Sache.Sie sollten klar angeben, was Ihre Methode erwartet, damit sie ordnungsgemäß funktioniert.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 nennen.Der Punkt ist: Wenn das System schnell ausfällt, wissen Sie, wo und warum es ausgefallen ist.Sie erhalten einen Stacktrace wie den folgenden:

 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 Sie werden 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 usw.

Andernfalls müssten Sie Validierungen über den gesamten Code verteilen, was fehleranfällig ist.Außerdem ist es manchmal schwer nachzuverfolgen, was schief gelaufen ist, und es kann sein, dass Sie mit stundenlangem, frustrierendem Debuggen rechnen müssen

Das Gleiche passiert mit NullPointerExceptions.Wenn Sie eine 700-Zeilen-Klasse mit etwa 15 Methoden haben, die 30 Attribute verwendet und keines davon null sein kann, könnten Sie, anstatt jede dieser Methoden auf Nullfähigkeit zu validieren, alle diese Attribute schreibgeschützt machen und sie im Konstruktor oder validieren 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 nützlich, wenn der Programmierer (Sie oder Ihre Kollegen) alles richtig gemacht hat, die Eingabe validiert, Tests durchgeführt hat und der gesamte Code perfekt ist, der Code jedoch eine Verbindung zu einem Webservice eines Drittanbieters herstellt, der möglicherweise nicht verfügbar ist (oder eine Datei, die Sie gespeichert haben). Die Verwendung wurde von einem anderen externen Prozess usw. gelöscht.Möglicherweise wird der Webservice sogar validiert, bevor eine Verbindung hergestellt wird, aber bei der Datenübertragung ist ein Fehler aufgetreten.

In diesem Szenario können Sie oder Ihre Kollegen nichts dagegen tun.Aber Sie müssen trotzdem etwas tun und dürfen nicht zulassen, dass die Anwendung einfach abstirbt und in den Augen des Benutzers verschwindet.Sie verwenden dafür eine geprüfte Ausnahme und behandeln die Ausnahme. Was können Sie tun, wenn das passiert? Meistens nur, um zu versuchen, den Fehler zu protokollieren, wahrscheinlich Ihre Arbeit (die App-Arbeit) zu speichern und dem Benutzer eine Nachricht zu übermitteln .(Die Seite blabla ist nicht erreichbar, bitte versuchen Sie es später erneut usw.)

Wenn die geprüfte Ausnahme überbeansprucht wird (durch Hinzufügen der „throw Exception“ in allen Methodensignaturen), wird Ihr Code sehr anfällig, da jeder diese Ausnahme ignoriert (weil sie zu allgemein ist) und die Qualität des Codes ernsthaft beeinträchtigt wird kompromittiert.

Wenn Sie die nicht aktivierte Ausnahme übermäßig verwenden, passiert etwas Ähnliches.Die Benutzer dieses Codes wissen nicht, ob etwas schief gehen könnte, und es werden viele try{...}catch( Throwable t ) angezeigt.

Hier ist meine „letzte Faustregel“.
Ich benutze:

  • ungeprüfte Ausnahme innerhalb des Codes meiner Methode für a Fehler durch den Anrufer (das beinhaltet eine explizite und vollständige Dokumentation)
  • geprüfte Ausnahme Für ein Ausfall aufgrund der Angerufener Das muss ich jedem deutlich machen, der meinen Code verwenden möchte

Im Vergleich zur vorherigen Antwort ist dies eine klare Begründung (der man zustimmen oder nicht zustimmen kann) für die Verwendung der einen oder anderen (oder beider) Art von Ausnahmen.


Für beide Ausnahmen erstelle ich meine eigene ungeprüfte und geprüfte Ausnahme für meine Anwendung (eine bewährte Vorgehensweise, wie hier erwähnt), mit Ausnahme einer sehr häufigen ungeprüften Ausnahme (wie NullPointerException)

Das Ziel dieser speziellen Funktion unten besteht beispielsweise darin, ein Objekt zu erstellen (oder abzurufen, falls bereits vorhanden).
Bedeutung:

  • Der Container des zu erstellenden/abrufenden Objekts MUSS vorhanden sein (Verantwortung des ANRUFERS).
    => ungeprüfte Ausnahme UND Javadoc-Kommentar für diese aufgerufene Funktion löschen)
  • Die anderen Parameter dürfen nicht null sein
    (Wahl des Codierers, das dem ANRUFER zuzuweisen:Der Codierer sucht nicht nach Nullparametern, DOKUMENTIERT ihn jedoch.
  • das Ergebnis DARF NICHT NULL SEIN
    (Verantwortung und Wahl des Codes des Angerufenen, Wahl, die für den Anrufer von großem Interesse sein wird
    => geprüfte Ausnahme, da jeder Aufrufer eine Entscheidung treffen MUSS, wenn das Objekt nicht erstellt/gefunden werden kann, und diese Entscheidung muss zum Zeitpunkt der Kompilierung erzwungen werden:Sie können diese Funktion nicht nutzen, ohne sich mit dieser Möglichkeit, also damit, auseinandersetzen zu müssen überprüft Ausnahme).

Beispiel:


/**
 * Build a folder. <br />
 * Folder located under a Parent Folder (either RootFolder or an existing Folder)
 * @param aFolderName name of folder
 * @param aPVob project vob containing folder (MUST NOT BE NULL)
 * @param aParent parent folder containing folder 
 *        (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob)
 * @param aComment comment for folder (MUST NOT BE NULL)
 * @return a new folder or an existing one
 * @throws CCException if any problems occurs during folder creation
 * @throws AssertionFailedException if aParent is not in the same PVob
 * @throws NullPointerException if aPVob or aParent or aComment is null
 */
static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent,
    final IPVob aPVob, final Comment aComment) throws CCException {
    Folder aFolderRes = null;
    if (aPVob.equals(aParent.getPVob() == false) { 
       // UNCHECKED EXCEPTION because the caller failed to live up
       // to the documented entry criteria for this function
       Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); }

    final String ctcmd = "mkfolder " + aComment.getCommentOption() + 
        " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName);

    final Status st = getCleartool().executeCmd(ctcmd);

    if (st.status || StringUtils.strictContains(st.message,"already exists.")) {
        aFolderRes = Folder.getFolder(aFolderName, aPVob);
    }
    else {
        // CHECKED EXCEPTION because the callee failed to respect his contract
        throw new CCException.Error("Unable to make/get folder '" + aFolderName + "'");
    }
    return aFolderRes;
}

Dabei kommt es nicht nur auf die Fähigkeit an, die Ausnahme zu beheben.Meiner Meinung nach kommt es vor allem darauf an, ob der Anrufer daran interessiert ist, die Ausnahme abzufangen oder nicht.

Wenn Sie eine Bibliothek schreiben, die an anderer Stelle verwendet werden soll, oder eine untergeordnete Ebene in Ihrer Anwendung, fragen Sie sich, ob der Aufrufer daran interessiert ist, Ihre Ausnahme abzufangen (zu erfahren).Ist dies nicht der Fall, verwenden Sie eine ungeprüfte Ausnahme, damit Sie ihn nicht unnötig belasten.

Dies ist die Philosophie, die von vielen Frameworks verwendet wird.Da fallen mir vor allem Spring und Hibernate ein – sie wandeln bekannte geprüfte Ausnahmen in ungeprüfte Ausnahmen um, gerade weil geprüfte Ausnahmen in Java übermäßig häufig verwendet werden.Ein Beispiel, das mir einfällt, ist die JSONException von json.org, die eine geprüfte Ausnahme ist und vor allem nervt – sie sollte deaktiviert sein, aber der Entwickler hat einfach nicht darüber nachgedacht.

Übrigens hängt das Interesse des Aufrufers an der Ausnahme meistens direkt mit der Fähigkeit zusammen, die Ausnahme zu beheben, aber das ist nicht immer der Fall.

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

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

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

wobei x null ist...…der Code sollte möglicherweise folgendes 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 einen nicht überprüfbaren Zustand vor, der auftreten kann, während der Code ausgeführt wird.

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, weil der DNS-Server ausgefallen ist.Selbst in dem Moment, in dem der DNS-Server funktionierte und den Namen „google.com“ in eine IP-Adresse auflöste, könnte das Netzwerk jederzeit ausfallen, wenn die Verbindung zu google.com hergestellt wird.Sie können das Netzwerk einfach nicht ständig testen, bevor Sie Streams lesen und schreiben.

Es gibt Zeiten, in denen der Code einfach ausgeführt werden muss, bevor wir erkennen können, ob ein Problem vorliegt.Indem ich Entwickler dazu zwinge, ihren Code so zu schreiben, dass sie diese Situationen per Checked Exception handhaben müssen, muss ich meinen Hut vor dem Java-Entwickler ziehen, der dieses Konzept erfunden hat.

Im Allgemeinen befolgen fast alle APIs in Java die beiden oben genannten Regeln.Wenn Sie versuchen, in eine Datei zu schreiben, könnte die Festplatte voll sein, bevor der Schreibvorgang abgeschlossen ist.Möglicherweise waren andere Prozesse dafür verantwortlich, dass die Festplatte voll wurde.Es gibt einfach keine Möglichkeit, diese Situation zu testen.Für diejenigen, die mit Hardware interagieren und deren Nutzung jederzeit fehlschlagen kann, scheinen Checked Exceptions eine elegante Lösung für dieses Problem zu sein.

Dabei gibt es eine Grauzone.Für den Fall, dass viele Tests erforderlich sind (eine umwerfende if-Anweisung mit vielen && und ||), wird die ausgelöste Ausnahme eine CheckedException sein, einfach weil es zu mühsam ist, es richtig zu machen – man kann dieses Problem einfach nicht sagen ist ein Programmierfehler.Wenn es deutlich weniger als 10 Tests gibt (z.B.„if (x == null)“), dann sollte der Programmiererfehler eine UncheckedException sein.

Interessant wird es im Umgang mit Sprachdolmetschern.Sollte ein Syntaxfehler gemäß den oben genannten Regeln als aktivierte oder nicht aktivierte Ausnahme betrachtet werden?Ich würde argumentieren, dass es sich um eine UncheckedException handeln sollte, wenn die Syntax der Sprache vor ihrer Ausführung getestet werden kann.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 beiden oben genannten Regeln werden wahrscheinlich 90 % Ihrer Bedenken hinsichtlich der Auswahl ausräumen.Befolgen Sie dieses Muster, um die Regeln zusammenzufassen… 1) Wenn der ausführende Code getestet werden kannWenn es sich um einen Programmierfehler handelt, sollte die Ausnahme eine UncheckedException (eine Unterklasse von RuntimeException) sein.2) Wenn der auszuführende Code vor der Ausführung nicht getestet werden kann, damit er ordnungsgemäß ausgeführt wird, sollte die Ausnahme eine geprüfte Ausnahme (eine Unterklasse von Exception) sein.

Sie können es als aktivierte oder nicht aktivierte Ausnahme bezeichnen.Jedoch, beide Arten von Ausnahmen können vom Programmierer abgefangen werden, daher ist die beste Antwort:schreiben alle Ihrer Ausnahmen als ungeprüft und dokumentieren sie.Auf diese Weise kann der Entwickler, der Ihre API verwendet, wählen, ob er oder sie diese Ausnahme abfangen und etwas unternehmen möchte.Geprüfte Ausnahmen sind eine völlige Zeitverschwendung und machen Ihren Code zu einem schockierenden Albtraum.Durch ordnungsgemäße Unit-Tests werden dann alle Ausnahmen angezeigt, die Sie möglicherweise abfangen und mit denen Sie etwas unternehmen müssen.

Geprüfte Ausnahme:Wenn der Client eine Ausnahme beheben kann und fortfahren möchte, verwenden Sie die aktivierte Ausnahme.

Ungeprüfte Ausnahme:Wenn ein Client nach der Ausnahme nichts mehr tun kann, lösen Sie eine ungeprüfte Ausnahme aus.

Beispiel:Wenn von Ihnen erwartet wird, dass Sie eine arithmetische Operation in einer Methode A() ausführen und diese auf der Ausgabe von A() basiert, müssen Sie eine andere Operation durchführen.Wenn die Ausgabe von Methode A() null ist, was Sie während der Laufzeit nicht erwarten, wird von Ihnen erwartet, dass Sie eine Nullzeigerausnahme auslösen, bei der es sich um eine Laufzeitausnahme handelt.

Verweisen Hier

Ich stimme grundsätzlich mit der Bevorzugung ungeprüfter Ausnahmen überein, insbesondere beim Entwerfen einer API.Der Aufrufer kann jederzeit eine dokumentierte, ungeprüfte Ausnahme abfangen.Sie zwingen den Anrufer einfach nicht unnötig dazu.

Ich finde geprüfte Ausnahmen auf der unteren Ebene als Implementierungsdetails nützlich.Es scheint oft ein besserer Kontrollmechanismus zu sein, als einen bestimmten Fehler-„Rückgabecode“ verwalten zu müssen.Manchmal kann es auch hilfreich sein, die Auswirkungen einer Idee für eine Codeänderung auf niedriger Ebene zu erkennen ...Deklarieren Sie eine geprüfte Ausnahme nachgelagert und sehen Sie, wer Anpassungen vornehmen muss.Dieser letzte Punkt gilt nicht, wenn es viele generische Elemente gibt: Catch (Ausnahme e) oder löst eine Ausnahme aus was meist sowieso nicht allzu gut durchdacht ist.

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

  1. Geprüfte Ausnahme.Dies ist ein Teil des Geschäftsanwendungsfalls oder Anrufablaufs, dies ist ein Teil der Anwendungslogik, die wir erwarten oder nicht erwarten.Zum Beispiel Verbindung abgelehnt, Bedingung ist nicht erfüllt usw.Wir müssen damit umgehen und dem Benutzer eine entsprechende Meldung mit Anweisungen darüber anzeigen, was passiert ist und was als nächstes zu tun ist (später erneut versuchen usw.).Normalerweise nenne ich es Nachverarbeitungsausnahme oder „Benutzer“-Ausnahme.

  2. Ungeprüfte Ausnahme.Dies ist ein Teil einer Programmierausnahme, ein Fehler bei der Softwarecode-Programmierung (Bug, Defekt) und spiegelt eine Art und Weise wider, wie Programmierer die API gemäß der Dokumentation verwenden müssen.Wenn ein externes Bibliotheks-/Framework-Dokument angibt, dass es erwartet, Daten in einem bestimmten Bereich und nicht null zu erhalten, weil NPE oder IllegalArgumentException ausgelöst wird, sollte der Programmierer damit rechnen und die API gemäß der Dokumentation korrekt verwenden.Andernfalls wird die Ausnahme ausgelöst.Normalerweise nenne ich es Vorverarbeitungsausnahme oder „Validierungsausnahme“.

Nach Zielgruppe.Lassen Sie uns nun über die Zielgruppe oder Personengruppe sprechen, für die Ausnahmen vorgesehen sind (meiner Meinung nach):

  1. Geprü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 Lebenszyklusphase der Anwendungsentwicklung.

  1. Eine 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. Ungeprüfte Ausnahmen sind so konzipiert, dass sie nur während des Anwendungsentwicklungs-/Testlebenszyklus vorhanden sind. Alle Ausnahmen sollten während dieser Zeit behoben werden und nicht ausgelöst werden, wenn eine Anwendung bereits in der Produktion ausgeführt wird.

Der Grund, warum Frameworks normalerweise ungeprüfte Ausnahmen verwenden (z. B. Spring), liegt darin, dass das Framework die Geschäftslogik Ihrer Anwendung nicht bestimmen kann. Dies liegt an den Entwicklern, dies zu erkennen und eine eigene Logik zu entwerfen.

Geprüfte Ausnahmen sind für wiederherstellbare Fälle nützlich, in denen Sie dem Anrufer Informationen zur Verfügung stellen möchten (z. B.unzureichende Berechtigungen, Datei nicht gefunden usw.).

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

Wenn eine Ausnahme mit geringerer Wahrscheinlichkeit erwartet wird und wir auch nach dem Abfangen dieser Ausnahme fortfahren können und nichts tun können, um diese Ausnahme zu vermeiden, können wir eine geprüfte Ausnahme verwenden.

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

Wenn eine Ausnahme in verschiedenen Ebenen navigiert, müssen wir sie nicht in jeder Ebene abfangen. In diesem Fall können wir eine Laufzeitausnahme verwenden oder eine Ausnahme als ungeprüfte Ausnahme umschließen.

Eine Laufzeitausnahme wird verwendet, wenn die Ausnahme höchstwahrscheinlich auftritt, es keine Möglichkeit gibt, weiterzugehen und nichts wiederhergestellt werden kann.In diesem Fall können wir also Vorkehrungen hinsichtlich dieser Ausnahme treffen.EX:NUllPointerException, ArrayOutofBoundsException.Es ist wahrscheinlicher, dass diese passieren.In diesem Szenario können wir beim Codieren Vorkehrungen treffen, um solche Ausnahmen zu vermeiden.Andernfalls müssen wir überall Try-Catch-Blöcke schreiben.

Allgemeinere Ausnahmen können deaktiviert, weniger allgemeine Ausnahmen aktiviert werden.

Ich denke, wir können über Ausnahmen von mehreren Fragen nachdenken:

Warum kommt es zu einer Ausnahme?Was können wir tun, wenn es passiert?

aus Versehen ein Fehler. Beispielsweise wird eine Methode mit einem Nullobjekt aufgerufen.

String name = null;
... // some logics
System.out.print(name.length()); // name is still null here

Diese Art von Ausnahme sollte während des Tests behoben werden.Andernfalls kommt es zu Produktionsunterbrechungen und es entsteht ein sehr schwerwiegender Fehler, der sofort behoben werden muss.Solche Ausnahmen müssen nicht geprüft werden.

durch Eingaben von außen, Sie können die Ergebnisse externer Dienste nicht kontrollieren oder ihnen vertrauen.

String name = ExternalService.getName(); // return null
System.out.print(name.length());    // name is null here

Hier müssen Sie möglicherweise prüfen, ob der Name null ist, wenn Sie fortfahren möchten, wenn er null ist. Andernfalls können Sie ihn in Ruhe lassen und er stoppt hier und gibt dem Aufrufer die Laufzeitausnahme.Solche Ausnahmen müssen nicht geprüft werden.

durch Laufzeitausnahme von extern, Sie können den externen Dienst nicht kontrollieren oder ihm vertrauen.

Hier müssen Sie möglicherweise alle Ausnahmen von ExternalService abfangen, wenn Sie fortfahren möchten, wenn es passiert. Andernfalls können Sie es in Ruhe lassen und es stoppt hier und gibt dem Aufrufer die Laufzeitausnahme.

durch geprüfte Ausnahme von extern, Sie können den externen Dienst nicht kontrollieren oder ihm vertrauen.

Hier müssen Sie möglicherweise alle Ausnahmen von ExternalService abfangen, wenn Sie fortfahren möchten, wenn es passiert. Andernfalls können Sie es in Ruhe lassen und es stoppt hier und gibt dem Aufrufer die Laufzeitausnahme.

Müssen wir in diesem Fall wissen, welche Art von Ausnahme in ExternalService aufgetreten ist? Es kommt darauf an:

  1. Wenn Sie mit einigen Arten von Ausnahmen umgehen können, müssen Sie diese abfangen und verarbeiten.Für andere, blasen Sie sie.

  2. Wenn Sie ein Protokoll oder eine Antwort für den Benutzer einer bestimmten Ausnahme benötigen, können Sie diese abfangen.Für andere, blasen Sie sie.

Wir müssen diese beiden Arten von Ausnahmen danach unterscheiden, ob es sich um einen Programmierfehler handelt oder nicht.

  • Wenn es sich bei einem Fehler um einen Programmierfehler handelt, muss es sich um eine ungeprüfte Ausnahme handeln. Zum Beispiel:SQLException/IOException/NullPointerException.Diese Ausnahmen sind Programmierfehler.Sie sollten vom Programmierer bearbeitet werden.Während in der JDBC -API SQLEXception -Ausnahme überprüft wird, ist es im Spring JDBCTEMPLTE eine deaktivierte Ausnahme. Programmer macht sich bei der Verwendung des Frühlings keine Sorgen um SQLEXception.
  • Wenn es sich bei einem Fehler nicht um einen Programmierfehler handelt und die Ursache extern ist, muss es sich um eine geprüfte Ausnahme handeln. Zum Beispiel:Wenn die Datei gelöscht oder die Dateiberechtigung von einer anderen Person geändert wird, sollte sie wiederhergestellt werden.

FileNotFoundException ist ein gutes Beispiel, um subtile Unterschiede zu verstehen.FileNotFoundException wird ausgelöst, falls die Datei nicht gefunden wird.Für diese Ausnahme gibt es zwei Gründe.Wenn der Dateipfad vom Entwickler definiert wird oder vom Endbenutzer über die GUI übernommen wird, sollte es sich um eine ungeprüfte Ausnahme handeln.Wenn die Datei von jemand anderem gelöscht wird, sollte es sich um eine geprüfte Ausnahme handeln.

Eine aktivierte Ausnahme kann auf zwei Arten behandelt werden.Diese verwenden Try-Catch oder propagieren die Ausnahme.Im Falle einer Ausnahmeweitergabe gilt dies für alle Methoden im Aufrufstapel eng verbunden wegen der Ausnahmebehandlung.Aus diesem Grund müssen wir Checked Exception sorgfältig verwenden.

Wenn Sie ein mehrschichtiges Unternehmenssystem entwickeln, müssen Sie größtenteils ungeprüfte Ausnahmen zum Auslösen auswählen. Vergessen Sie jedoch nicht, aktivierte Ausnahmen zu verwenden, falls Sie nichts tun können.

Ich denke, wenn man eine Anwendungsausnahme deklariert, sollte es sich um eine ungeprüfte Ausnahme handeln, d. h. um eine Unterklasse von RuntimeException.Der Grund dafür ist, dass der Anwendungscode nicht durch Try-Catch und Throws-Deklaration für die Methode überladen wird.Wenn Ihre Anwendung Java API verwendet, werden geprüfte Ausnahmen ausgelöst, die ohnehin behandelt werden müssen.In anderen Fällen kann die Anwendung eine ungeprüfte Ausnahme auslösen.Wenn der Anwendungsaufrufer weiterhin ungeprüfte Ausnahmen verarbeiten muss, ist dies möglich.

Die Regel, die ich verwende, ist:Verwenden Sie niemals ungeprüfte Ausnahmen!(Oder wenn Sie keinen Ausweg mehr sehen)

Aus der Sicht des Entwicklers, der Ihre Bibliothek verwendet, oder des Endbenutzers, der Ihre Bibliothek/Anwendung verwendet, ist es wirklich ärgerlich, mit einer Anwendung konfrontiert zu werden, die aufgrund einer nicht behandelten Ausnahme abstürzt.Und sich auf einen Alleskönner zu verlassen, nützt auch nichts.

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top