Schrittweises Verständnis der Behandlung von Java-Ausnahmen

Einführung

Das Problem der Ausnahmebehandlung ist ein häufiges Problem bei Java-Codeüberprüfungen. Wie in diesem Artikel erwähnt, sind die Grundregeln für die Behandlung von Java-Ausnahmen nicht so kompliziert. Leider wird häufig beobachtet, dass selbst Java-Programmierer mit langjähriger Berufserfahrung keine ordnungsgemäße Ausnahmebehandlung implementieren können. Ganz zu schweigen von Java-Programmierern mit weniger Erfahrung.

Warum ist eine unsachgemäße Ausnahmebehandlung so verbreitet? Es gibt drei Hauptfaktoren, die berücksichtigt werden können. Erstens gibt es historische Verwirrung im Ausnahmemechanismus (insbesondere geprüfte Ausnahmen) in der Java-Sprachspezifikation, was Programmierern übermäßige Freiheit gibt. Zweitens sollten Sie die schädlichen Auswirkungen einer unangemessenen Ausnahmebehandlung nicht bemerken, es sei denn, Sie entwickeln die Anwendung nicht nur, sondern betreiben sie auch tatsächlich. Schließlich gibt es keine kompakte Sammlung von Ressourcen, um die richtige Behandlung von Ausnahmen zu erlernen. In Anfängerbüchern ist die Ad-hoc-Ausnahmebehandlung, die das Auftreten von "e.printStackTrace ()" verursacht, auffällig, und geeignete Methoden zur Ausnahmebehandlung sind in Büchern und Framework-Dokumenten für Zwischenbenutzer und höher verteilt.

Daher werden wir in diesem Artikel für Anfänger, Anfänger und Fortgeschrittene drei Phasen einteilen, wie die Falle einer übermäßigen Freiheit der Ausnahmebehandlung vermieden werden kann und welche Ausnahmebehandlung aus betrieblicher Sicht angemessen ist. Ich möchte es kompakt machen. Es wird hauptsächlich angenommen, dass sich die Zielanwendung auf der Serverseite befindet (obwohl viele Elemente nicht nur auf der Serverseite anwendbar sein sollten).

Für Anfänger

Hier sind einige Dinge zu verstehen, bevor Sie zur Szene gehen.

Verstehen Sie die Eigenschaften des Ausnahmemechanismus

Darstellung eines anomalen Systems

Es gibt ein großes Problem mit diesem Code, der ein abnormales System von Methodenaufrufen mit einem speziellen Rückgabewert ausdrückt. Erstens kann der Aufrufer von "createItem ()" vergessen, eine anomale Verarbeitung zu implementieren. Außerdem weiß der Anrufer nicht, was tatsächlich falsch war, sondern nur, dass der Rückgabewert leer ist.

Item item = createItem();
if (item == null) {
    //Anormales System
    ...
} else {
    //Normales System
    ...
}

Mit der Einführung des Ausnahmemechanismus kann der Code wie folgt umgeschrieben werden: Infolgedessen kann der Anrufer angewiesen werden, die abnormale Verarbeitung explizit zu implementieren. Darüber hinaus kann der Aufrufer die Details der Anomalie aus der Ausnahmemeldung und der Stapelverfolgung abrufen, die in der catch-Klausel abgefangen sind.

try {
    Item item = createItem();
    //Normales System
    ...
} catch (ItemCreationException e) {
    //Anormales System
    ...
}

Unterstützung für mehrstufige Anrufhierarchie

Wenn Sie den Ausnahmemechanismus verwenden, können Sie auch in einer mehrstufigen Anrufhierarchie einfach mit abnormalen Systemen umgehen. Beispielsweise weisen Anwendungen mit einer typischen Schichtarchitektur diese mehrstufige Anrufhierarchie auf (auf Anfängerebene müssen Sie sich nicht um die Details kümmern, wenn Sie etwas Kompliziertes finden).

Das Problem hierbei ist, wie das abnormale System in der unteren Schicht zur oberen Schicht transportiert werden kann. Angenommen, wenn beim Datenzugriff der untersten Schicht ein Fehler auftritt, muss bei der Nachbearbeitung der höchsten Schicht eine entsprechende Fehlerantwort zurückgegeben werden. Um diese Anforderung mit einem speziellen Rückgabewert zu erfüllen, muss ein abnormaler Rückgabewert in einer Bucket-Relay-Weise von der niedrigsten Schicht zur höchsten Schicht zurückgegeben werden.

Andererseits ist es durch Verwendung eines Ausnahmemechanismus anstelle eines speziellen Rückgabewerts möglich, eine Abnormalität in einer beliebigen unteren Schicht in einer beliebigen oberen Schicht zu behandeln, während die Eingabe / Ausgabe der Methode einfach gehalten wird. Die untere Ebene löst nur eine Ausnahme wie "Neue IllegalStateException auslösen (" Etwas stimmt nicht ")" aus, ohne darüber nachzudenken, und eine obere Ebene fängt nur die Ausnahme in der "catch" -Klausel ab.

Verstehen Sie den Unterschied zwischen aktivierten und nicht aktivierten Ausnahmen

Ausnahmeklassenhierarchie

Unten finden Sie einen grundlegenden Vererbungsbaum für Ausnahmeklassen (beachten Sie, dass alle Pakete "java.lang" sind). Ausnahmen, die von "Ausnahme" erben, sind geprüfte Ausnahmen, und Ausnahmen, die von RuntimeException erben, sind geprüfte Ausnahmen. Beachten Sie, dass "Throwable" und "Error" kein detailliertes Verständnis für Anfänger erfordern (es ist besser, sie nicht zu berühren).

Geprüfte Ausnahme

Aktivierte Ausnahmen sind Ausnahmen, die den Anrufer zwingen, Maßnahmen zu ergreifen. Wenn Sie beispielsweise den Code schreiben, der den Inhalt der Datei wie unten gezeigt liest, wird ein Kompilierungsfehler ausgegeben.

List<String> lines = Files.readAllLines(Paths.get("items.csv"));
Error:(x, x) java:Ausnahme Java.io.Es wird keine IOException gemeldet. Muss gefangen genommen oder zum Werfen erklärt werden

Hier gibt es zwei Schritte, mit denen Sie die Zusammenstellung aus der Perspektive eines Anfängers durchführen können. Erstens gibt es eine Methode zum Fangen mit Try-Catch. Beachten Sie, dass nach der Erfassung hier viele Fallen in der Verarbeitung vorhanden sind (geeignete Maßnahmen werden später beschrieben).

try {
    List<String> lines = Files.readAllLines(Paths.get("items.csv"));
    //Normales System
    ...
} catch (IOException e) {
    //Anormales System
    ...
}

Alternativ können Sie es dem Aufrufer in der throw-Klausel der Methode explizit überlassen. Es gibt jedoch nicht viele Situationen, in denen diese Methode verwendet werden kann. Details werden im Abschnitt für fortgeschrittene Benutzer beschrieben.

public void processItems() throws IOException {
    List<String> lines = Files.readAllLines(Paths.get("items.csv"));
    //Normales System
    ...
}

Deaktivierte Ausnahme

Nicht aktivierte Ausnahmen sind Ausnahmen, z. B. aktivierte Ausnahmen, die vom Aufrufer nicht erzwungen werden. Beispielsweise kann die Methode "Integer.parseInt (String)" eine ungeprüfte Ausnahme "NumberFormatException" auslösen (Referenz: Javadoc. /api/java/lang/Integer.html#parseInt-java.lang.String-)), aber es wird kein Kompilierungsfehler ausgegeben. Stattdessen tritt zur Laufzeit ein Fehler auf.

Integer value = Integer.parseInt("ABC"); //Kompilieren, ohne etwas zu tun
java.lang.NumberFormatException: For input string: "ABC"

Inspektionsausnahmen überwinden

In RuntimeException einschließen und senden

Denken Sie jetzt daran, was zu tun ist, wenn Sie eine aktivierte Ausnahme abfangen, um sie durch die Kompilierung zu bringen, und wie Sie sie in diese "RuntimeException" einschließen und auf Anfängerebene senden. Sie müssen nicht im Detail wissen, was mit den ungeprüften Ausnahmen passiert, die Sie auf Anfängerebene auslösen. Mach nichts extra.

try {
    List<String> lines = Files.readAllLines(Paths.get("items.csv"));
    //Normales System
    ...
} catch (IOException e) {
    throw new RuntimeException(e); //In ungeprüfte Ausnahme einschließen und senden
}

Wrap und senden Sie geeignetere ungeprüfte Ausnahmen

RuntimeException Es wäre sogar noch besser, wenn Sie es in eine entsprechende ungeprüfte Ausnahme einschließen und senden könnten, anstatt sich nur darauf zu konzentrieren. Im Folgenden sind einige häufig verwendete ungeprüfte Ausnahmen und ihre sehr groben Verwendungen aufgeführt.

Tatsächlich ist es also besser, den in der obigen RuntimeException eingeschlossenen Code neu zu schreiben, um UncheckedIOException zu verwenden.

try {
    List<String> lines = Files.readAllLines(Paths.get("items.csv"));
    //Normales System
    ...
} catch (IOException e) {
    throw new UncheckedIOException(e); //Wrap und senden Sie geeignetere ungeprüfte Ausnahmen
}

Für Anfänger

Hier beschreiben wir, was Sie verstehen müssen, wenn Sie unter der Leitung von jemandem auf dem Gebiet entwickeln und arbeiten.

Kennen Sie die verbotene Hand der Ausnahmebehandlung

Wie oben erwähnt, können Sie in den meisten Fällen minimal sicheren Code schreiben, indem Sie nur daran denken, ihn in eine ungeprüfte Ausnahme einzuschließen und zu versenden. Aus irgendeinem Grund neigen Java-Programmierer jedoch dazu, von der Mindestzeile abzuweichen, indem sie zusätzliche Dinge tun oder das Wesentliche vergessen. Im Folgenden sind häufig nicht ordnungsgemäße Ausnahmebehandlungen aufgeführt. Bitte imitieren Sie es nicht.

(Verbotene Hand) Crush

Die erste verbotene Hand zerquetscht. Infolge des Zusammendrückens tritt bei der nachfolgenden Verarbeitung ein Problem auf, von dem erwartet wurde, dass es das richtige Ergebnis der ursprünglich ausgeführten Verarbeitung liefert. Ein typisches Problem ist "NullPointerException". Im Allgemeinen gibt es einige Fälle, in denen "NullPointerException" in Java als Bösewicht behandelt wird, aber nichts hier ist, dass Ihr eigener Code schlecht ist, nicht "NullPointerException".

List<String> lines = null;
try {
    lines = Files.readAllLines(Paths.get("items.csv"));
} catch (IOException e) {
    //zerquetschen
}
lines.stream().forEach(...); //Ich erhalte eine NullPointerException, da die Zeilen hier immer noch null sind

Es gibt jedoch nur wenige Fälle, die mit Willen zerquetscht werden sollten. In diesem Fall ist es besser, die Absicht in einem Protokoll oder einem Kommentar klar anzugeben.

(Verboten) Der Ausgabestapel verfolgt und protokolliert in dem Umfang, in dem

In der Grundierung wird häufig der Code angezeigt, der "e.printStackTrace ()" in der "catch" -Klausel aufruft. Dies ist in Ordnung, in Java-Anwendungen der realen Welt jedoch fast nicht akzeptabel. Ich versuche, eine Nachricht mit "e.printStackTrace ()" zu drucken, aber wenn ich die Verarbeitung fortsetze, unterscheidet sich dies nicht wesentlich vom Ausdrücken von Ausnahmen. Außerdem ist das Ausgabeziel von "e.printStackTrace ()" im Allgemeinen eine Standardfehlerausgabe. Im Gegensatz zu Protokollen fehlen Metainformationen wie Datum und Uhrzeit sowie die Anforderungs-ID, die zur Untersuchung der Ursache hilfreich sind. Wenn Sie solchen Code unbeaufsichtigt lassen, werden Sie von einer mysteriösen Stapelverfolgung geplagt, die Sie während des Betriebs nicht finden können, um sie zu lösen.

List<String> lines = null;
try {
    lines = Files.readAllLines(Paths.get("items.csv"));
} catch (IOException e) {
    e.printStackTrace(); //Entschuldigung für die Ausgabe des Stack-Trace
}
lines.stream().forEach(...); //Irgendwann bekomme ich hier eine NullPointerException

Selbst wenn das obige "e.printStackTrace ()" durch eine Protokollausgabe wie "log.warn" ersetzt wird ("Elemente konnten nicht gelesen werden:" + e, e) "", wird das Problem der Metainformationen in der Ausgabe gelöst. Es ist insofern dasselbe, als wenn die Verarbeitung fortgesetzt wird, es nicht viel anders ist, als die Ausnahme zu zerstören.

(Verbotene Hand) Melden Sie sich selbst an und senden Sie sie erneut

Es ist diese verbotene Hand, die ein akribischer Anfänger gerne macht. Nachdem das eigene Protokoll einzeln ausgegeben wurde, wird das durch dasselbe Problem verursachte Protokoll erneut vom später beschriebenen globalen Ausnahmebehandler ausgegeben. Diese sehen aus wie zwei Arten von Ausnahmeprotokollen für unterschiedliche Probleme im Betrieb und verursachen Verwirrung. In der Welt der Erwachsenen ist es nicht unbedingt gut, vorsichtig zu sein.

List<String> lines = null;
try {
    lines = Files.readAllLines(Paths.get("items.csv"));
} catch (IOException e) {
    log.warn("Could not read items: " + e, e); //Die Akribie schlägt fehl
    throw new UncheckedIOException(e);
}
lines.stream().forEach(...);

Wenn Sie eine Nachricht einschließen möchten, senden Sie sie als Ausnahmemeldung.

List<String> lines = null;
try {
    lines = Files.readAllLines(Paths.get("items.csv"));
} catch (IOException e) {
    throw new UncheckedIOException("Could not read items", e); //Lässig ansprechen
}
lines.stream().forEach(...);

(Verboten) Wirf eine weitere Ausnahme aus

Es gibt einige Fehler, die den "Wrap" von "Wrap and Send to Unchecked Exception" vergessen und einfach eine weitere ungeprüfte Ausnahme auslösen. Der negative Effekt in diesem Fall ist, dass die Grundursache der Ausnahme während des Betriebs nicht bekannt ist. Beispielsweise gibt es verschiedene mögliche Ursachen für Ausnahmen, die beim Zugriff auf eine Datei auftreten, z. B. die Tatsache, dass die Datei nicht vorhanden ist oder dass Sie keinen Zugriff auf die Datei haben. Wenn Sie vergessen, die Ausnahme, die die Grundursache angibt, zu verpacken und eine weitere Ausnahme zu senden, wird die Fehleranalyse während des Betriebs schwierig.

List<String> lines = null;
try {
    lines = Files.readAllLines(Paths.get("items.csv"));
} catch (IOException e) {
    throw new IllegalStateException("Could not read items"); //Informationen, die in der ursprünglichen Ausnahme enthalten sein sollten, gehen verloren
}
lines.stream().forEach(...);

(Verboten) Vergessen Sie, die Ressource zu schließen

Wenn die offene Verarbeitung einer Ressource wie einer Datei- oder Datenbankverbindung ausgeführt wird, muss die Abschlussverarbeitung im Prinzip danach durchgeführt werden (ob die Abschlussverarbeitung unbedingt erforderlich ist oder nicht, wird unter Bezugnahme auf das Javadoc der offenen Verarbeitungsmethode bestimmt. Ding). Ein häufiger nachteiliger Effekt des Vergessens des Schließens ist das sogenannte Speicherleck. In vielen Fällen wird das Problem jedoch nicht unmittelbar nach der Freigabe entdeckt, und es wird bei der anschließenden Operation wie eine zeitgesteuerte Bombe. Sobald die Website entdeckt wurde, wird sie durch vorläufige Vorgänge wie die Suche nach dem Verbrecher und den regelmäßigen Neustart erschöpft.

try {
    BufferedReader in = Files.newBufferedReader(Paths.get("items.csv"));
    in.lines().forEach(...);
    //in ist nicht geschlossen
} catch (IOException e) {
    throw new UncheckedIOException(e);
}

Verwenden Sie stattdessen die Try-with-Resources-Syntax.

try (BufferedReader in = Files.newBufferedReader(Paths.get("items.csv"))) {
    in.lines().forEach(...);
} catch (IOException e) {
    throw new UncheckedIOException(e);
}

Vor der Einführung der Try-with-Resources-Syntax wurde der Abschlussprozess in der Klausel "finally" ausgeführt, ist jedoch redundant und schwer zu lesen, und es gibt viele Dinge zu beachten, wenn in der Klausel "finally" eine Ausnahme auftritt, die kompliziert ist. Es ist sicher, es im Anfängerstadium zu vermeiden.

BufferedReader in = null;
try {
    in = Files.newBufferedReader(Paths.get("items.csv"));
    in.lines().forEach(...);
} catch (IOException e) {
    throw new UncheckedIOException(e);
} finally {
    try {
        in.close();
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}

Als Referenz kann Try-with-Resources nur verwendet werden, wenn die Zielklasse die Schnittstelle "java.io.Closeable" oder die Schnittstelle "java.lang.AutoCloseable" implementiert. Weitere Informationen finden Sie unter Offizielle Dokumente.

(Verboten) Wiederholen Sie denselben Vorgang für mehrere Ausnahmen

Es gibt fast keinen Betriebsschaden für diese verbotene Person, aber es ist immer noch nicht gut, dass der Code nicht lesbar ist.

try {
    Item item = createItem();
    //Normales System
    ...
} catch (ItemCreationException e) {
    throw new IllegalStateException(e);
} catch (InvalidProcessingException e) {
    throw new IllegalStateException(e);
}

Verwenden Sie stattdessen Multi-Catch.

try {
    Item item = createItem();
    //Normales System
    ...
} catch (ItemCreationException | InvalidProcessingException e) {
    throw new IllegalStateException(e);
}

Defensive Verwendung ungeprüfter Ausnahmen

Nicht aktivierte Ausnahmen können auch verwendet werden, um Bedingungen wie "Nur diese Parameter sollten hierher kommen" und "Dieser Prozess sollte nicht ausgeführt werden" defensiv auszudrücken.

Eine übliche Anwendung besteht darin, eine "IllegalArgumentException" für einen ungültigen Parameter in der Guard-Klausel am Anfang der Methode auszulösen.

public void processItem(Item item) {
    if (!item.isValid()) {
        //Ungültiger Parameter
        throw new IllegalArgumentException("Invalid item: " + item);
    }
    //Normales System
    ...
}

Der obige Code lautet wie folgt: Voraussetzungen von Guava Kann in einer Zeile geschrieben werden. Ich kann es nicht laut aussprechen, aber wenn Sie die "nur für den Fall" -Pegelverzweigung nicht mögen, die die Abdeckung von Komponententests verringert, ist dies eine gute Option.

public void processItem(Item item) {
    Preconditions.checkArgument(item.isValid(), "Invalid item: %s", item);
    //Normales System
    ...
}

In ähnlicher Weise ist es bei der Suche nach Nullparametern besser, die Standardklassenbibliothek "java.util.Objects.requireNonNull (T)" anstelle Ihrer eigenen if-Anweisung zu verwenden. Die hier ausgelöste Ausnahme ist übrigens die berüchtigte "NullPointerException". Guavas ähnliche Funktion, "Preconditions.checkNotNull (T)", löst auch eine "NullPointerException" aus, was ein bisschen Widerstand ist. Wickeln wir es um ein langes Objekt.

public void processItem(Item item) {
    Objects.requireNonNull(item, "Item is null");
    //Normales System
    ...
}

Darüber hinaus wird möglicherweise eine Ausnahme im normalerweise nicht erreichbaren Standardteil der switch-Anweisung ausgelöst.

Result result = processItem(item);
switch (result) {
    case SUCCEEDED:
        ...
        break;
    case FAILED:
        ...
        break;
    ...
    default:
        throw new IllegalStateException("This would not happen");
}

Reagieren Sie global auf Ausnahmen

Bisher hat sich die Beschreibung hauptsächlich auf die Seite konzentriert, die die Ausnahme auslöst. Als Nächstes werden wir jedoch beschreiben, wie mit der ausgelösten Ausnahme umgegangen wird.

(Fast verboten) Implementieren Sie Ihren eigenen Try-Catch-Prozess oben in der Anrufhierarchie

Die einfachste und einfachste Möglichkeit, Ausnahmen abzufangen, besteht darin, einen eigenen endgültigen Try-Catch-Prozess oben in der Aufrufhierarchie zu schreiben (Hauptmethode für Befehlszeilenanwendungen oder Presentation Layer Controller für Webanwendungen). In der Realität gibt es jedoch nur wenige Möglichkeiten, diese Methode anzuwenden. In der realen Java-Anwendungsentwicklung gibt es einige Fälle, in denen die Hauptmethode vollständig implementiert ist, und es gibt eine bessere Alternative zum Webframework für den Presentation Tier Controller.

Verwenden Sie den Ausnahmebehandlungsmechanismus des Webframeworks

Moderne Webframeworks bieten einen Mechanismus zum Ausführen von Ausnahmebehandlungsroutinen entsprechend der auftretenden Ausnahmeklasse. Der Vorteil eines solchen Mechanismus besteht darin, dass die gemeinsame Verarbeitung mehrerer Controller flexibel kombiniert werden kann, ohne die Vererbungsstruktur der Controller-Klasse zu verwenden. Der Mechanismus zur Ausnahmebehandlung in einem typischen Webframework wird unten gezeigt.

Verwenden Sie den Interceptor-Mechanismus des DI-Containers

Ein allgemeinerer Mechanismus ist der DI-Container-Interceptor-Mechanismus. Mit dem Interceptor-Mechanismus können Sie die Vor- und Nachbearbeitung für jeden Methodenaufruf in einer Klasse unter der Kontrolle eines DI-Containers einfügen. Der Interceptor-Mechanismus in einem typischen DI-Container ist unten gezeigt.

Die typische Verarbeitung, die mithilfe des Interceptor-Mechanismus für Ausnahmen realisiert wird, ist die Transaktionssteuerung (wird automatisch zurückgesetzt, wenn eine Ausnahme nach einer bestimmten Methode auftritt). Der Transaktionssteuerungsmechanismus in einem typischen DI-Container ist unten gezeigt.

Definieren Sie Ihre eigene Ausnahme

Wenn Sie Ausnahmen global nach Klassen behandeln können, möchten Sie Ihre eigenen Ausnahmen erstellen. Beispielsweise möchten Sie möglicherweise eine personalisierte Fehlerantwort zurückgeben, die für eine bestimmte Geschäftslogik oder eine externe API-Zugriffslogik spezifisch ist. Um eine eigene Ausnahme zu erstellen, können Sie von der vorhandenen Ausnahmeklasse erben und den Konstruktor überschreiben.

public class ItemCreationException extends RuntimeException {
	public ItemCreationException() {
	}

	public ItemCreationException(String message) {
		super(message);
	}

	public ItemCreationException(Throwable cause) {
		super(cause);
	}

	public ItemCreationException(String message, Throwable cause) {
		super(message, cause);
	}

	public ItemCreationException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}
}

Auf den ersten Blick mag die Menge an Code groß erscheinen, aber die Arbeit ist gering, da sie tatsächlich von der IDE generiert wird. Im Fall von Eclipse geben Sie beispielsweise im Dialogfeld für die neue Klassengenerierung einfach den Namen der Superklasse an und überprüfen Sie die Generierung des Generators.

Für fortgeschrittene Benutzer

Hier beschreiben wir, was Sie verstehen sollten, wenn Sie nach eigenem Ermessen vor Ort entwickeln und arbeiten.

Geben Sie das Ausnahmeprotokoll auf einer geeigneten Ebene aus und arbeiten Sie

Für Ausnahmen, die vom globalen Ausnahmebehandler behandelt werden, ist es erforderlich, ein Protokoll auf einer geeigneten Ebene auszugeben und tägliche Vorgänge auszuführen. Das Folgende ist ein Beispiel für die Richtlinie zur ordnungsgemäßen Verwendung von Ebenen und zum Betrieb. Dies ist nur ein Beispiel, und jedes Team hat unterschiedliche Richtlinien.

Es ist jedoch im Allgemeinen schwierig, die Regeln unmittelbar nach der Veröffentlichung strikt anzuwenden, und in der Realität werden die oben genannten Vorgänge Schritt für Schritt durch Abschneiden der Phase entwickelt.

Reagieren Sie auf einzelne Ausnahmen

In realen Java-Anwendungen kann anstelle einer globalen Ausnahmebehandlung eine Ausnahmebehandlung erforderlich sein, die für eine bestimmte Funktion spezifisch ist. Die folgenden Fälle sind typische Beispiele.

Gibt einen anderen Rückgabewert zurück

Wenn es für die untere Ebene nicht beabsichtigt ist, eine Ausnahme auszulösen, kann sie die Ausnahme abfangen und einen anderen Rückgabewert zurückgeben. Der folgende Code fängt beispielsweise eine Ausnahme ab, die angibt, dass der Datensatz beim Zugriff auf die Datenbank nicht vorhanden ist, und gibt stattdessen einen optionalen Rückgabewert zurück.

public Optional<Item> findByName(String name) {
    try {
        Item item = entityManager.createQuery("...", Item.class).setParameter(1, name).getSingleResult();
        return Optional.of(item);
    } catch (NoResultException e) {
        return Optional.empty();
    }
}

Beachten Sie, dass Sie kein Design auswählen sollten, das null anstelle von Optional zurückgibt. Weitere Informationen finden Sie unter Twitter-Suchergebnisse für "null kill". ..

Wiederholen

Bei der Verarbeitung wie einem externen API-Aufruf kann eine Ausnahme abgefangen werden, die auf einen versehentlichen Kommunikationsfehler hinweist, und die Wiederholungsverarbeitung kann ausgeführt werden. Wenn Sie jedoch versuchen, die Wiederholungsverarbeitung ernsthaft zu implementieren, müssen Sie überraschend viele Dinge berücksichtigen, z. B. die Einstellung der Zeitüberschreitungszeit, die Einstellung der Wiederholungsanzahl, den Backoff-Algorithmus, die Bewältigung des gleichzeitigen Auftretens von Wiederholungen, die Überwachung des Status des erneuten Auftretens von Wiederholungen usw. Anstatt es selbst zu implementieren, Microprofile Retry und [Spring Retry](https :: Es wäre sicherer, eine Bibliothek wie //github.com/spring-projects/spring-retry) zu verwenden. In Zukunft wird erwartet, dass diese Logik von Service Mesh-Mechanismen wie Istio außerhalb der Anwendung übernommen wird.

Führen Sie eine andere alternative Verarbeitung durch

Zusätzlich kann eine alternative Verarbeitung gemäß den Anforderungen durchgeführt werden. Da der Verarbeitungsinhalt von Fall zu Fall erfolgt, werden Details weggelassen.

Nutzen Sie geprüfte Ausnahmen

Abschließend werde ich erklären, wie die überprüften Ausnahmen verwendet werden, die ich bisher vermieden habe.

Erstens gibt es für Bibliotheken und Frameworks auf niedriger Ebene Fälle, in denen die Überprüfung von Ausnahmen angemessen verwendet werden sollte, wie dies beim Paket "java.io" der Fall ist.

Für die Geschäftslogik ist die Verwendung einer Prüfausnahme eine Option, wenn Sie den Anrufer zwingen möchten, abnormale Systeme zu verarbeiten. Das folgende Beispiel zeigt eine Methode, die eine aktivierte Ausnahme verwendet, und eine Methode, die eine Aufzählung zurückgibt. Die Methode, die geprüfte Ausnahmen verwendet, hat eine einfache Methodensignatur, und eine ähnliche Verarbeitung kann unter Verwendung der Ausnahmevererbungsstruktur gemeinsam genutzt werden. Andererseits ist bei der Methode der Rückgabe mit enum leicht zu verstehen, dass der Aufrufer den Rückgabewert umfassend behandelt. Welche Sie wählen müssen, ist von Fall zu Fall.

public void sendNotification(Member member, Notification notification) throws InvalidMemberException {
    //Methode mit Prüfausnahme
    ...
}
try {
    sendNotification(member, notification);
    //Normales System
    ...
} catch (InvalidMemberException e) {
    //Alternative Verarbeitung
    ...
}
public NotificationResult sendNotification(Member member, Notification notification) {
    //Methode, um mit enum zurückzukehren
    ...
}
NotificationResult result = sendNotification(member, notification);
switch (result) {
    case SUCCEEDED:
        //Normales System
        ...
        break;
    case INVALID_MEMBER:
        //Alternative Verarbeitung
        ...
        break;
    ...
}

abschließend

Bisher haben wir in drei Schritten gezeigt, was Sie über die Ausnahmebehandlung in realen Java-Anwendungen verstehen müssen: Anfänger, Anfänger und Fortgeschrittene. Wir hoffen, dass dieser Artikel unproduktive Codeüberprüfungen und schmerzhafte Anwendungsvorgänge so weit wie möglich reduziert.

Recommended Posts

Schrittweises Verständnis der Behandlung von Java-Ausnahmen
[Java] Praxis der Ausnahmebehandlung [Ausnahme]
Java-Ausnahmebehandlung?
[Java] Ausnahmebehandlung
☾ Java / Ausnahmebehandlung
Informationen zur Behandlung von Java-Ausnahmen
Behandlung von Java-Ausnahmen
[Java] Anfängerverständnis von Servlet-②
[Java] Anfängerverständnis von Servlet-①
[Java] Informationen zur Behandlung von Try-Catch-Ausnahmen
Verwendungsregeln für die Behandlung von Java-Ausnahmen
Ausnahmebehandlungstechniken in Java
[Inhouse-Studiensitzung] Behandlung von Java-Ausnahmen (26.04.2017)
Umgang mit Zeitzonen mit Java
Ausnahmebehandlung
[Hinweis] Behandlung von Java-Dezimalstellen
Schrittweises Verständnis der O / R-Zuordnung
[Für Java-Anfänger] Informationen zur Ausnahmebehandlung
Ausnahmebehandlung Ausnahme
Java (Ausnahmebehandlung, Threading, Sammlung, Datei-E / A)
try-catch-finally Ausnahmebehandlung Verwendung von Java
Informationen zur Ausnahmebehandlung
Informationen zur Ausnahmebehandlung
Behandlung von Ruby-Ausnahmen
[Java] Ausnahmeinstanz
Ruby-Ausnahmebehandlung
[Java] Übersicht über Java
[Java] Behandlung von Java Beans in der Methodenkette
Fragen in Java-Ausnahmebehandlung werfen und versuchen-fangen
Abgelaufene Java-Sammlung
Voraussichtliche Funktionen von Java
[Java] Bedeutung der serialVersionUID
Informationen zur Behandlung von Ruby-Ausnahmen
Praxis der Ausnahmebehandlung (ArithmeticException)
NIO.2 Überprüfung von Java
Bewertung von Java Shilber
[Java] Wirf eine Ausnahme aus
Java - Vereinigung von Kommentaren
Spring Boot-Ausnahmebehandlung
Geschichte der Java-Annotationen
Java (Verdienste des Polymorphismus)
[Java] Beim Schreiben der Quelle ... Memorandum ①
"Nr. 1 Verständnis für diese Art von Dingen" Tomcat [Java] neu starten
[Java Silver] (Ausnahmebehandlung) Informationen zu den Anweisungen try-catch-finally und try-with-resource
NIO Bewertung von Java
[Java] Drei Funktionen von Java
Zusammenfassung der Java-Unterstützung 2018
[Java] Umgang mit Zeichenketten (String-Klasse und StringBuilder-Klasse)
"So etwas verstehen Nr. 2" Volumen der Vergleichsoperatoren [Java]
Empfehlung der Set-Operation durch Java (und Verständnis von Equals und HashCode)
Wiedereinführung in Java for Humanities 0: Den Akt der Programmierung verstehen
[Einführung in Java] Umgang mit Zeichenfolgen (String-Klasse, StringBuilder-Klasse)
Über den Umgang mit Null
Klassen, die eine Ausnahmebehandlung erfordern
Java Basic Learning Content 7 (Ausnahme)
Über Java-Instanzen
[Java] Mirage-Basic-Verwendung von SQL
Javas erste Ausnahmebehandlung (Denkmal)