Der Ausnahmebehandlungsmechanismus in Java ist relativ ausgereift. Unsere Java-Programme sind voller Ausnahmemöglichkeiten. Wenn diese Ausnahmen nicht im Voraus behandelt werden, wird es in Zukunft unmöglich sein, den Programmabsturz zu debuggen Finden Sie den Ort der Ausnahme. In diesem Artikel wird erläutert, wie Ausnahmen und Fehler in Java behandelt werden. Werfen wir einen Blick darauf.
Ausnahmen und Fehler:
Ausnahme:
Programmfehler in Java sind hauptsächlich Syntaxfehler und Semantikfehler, die beim Kompilieren und Ausführen eines Programms auftreten werden zusammenfassend als Ausnahmen bezeichnet. Sie sind eine Möglichkeit für die VM (virtuelle Maschine), Sie darüber zu informieren, dass Sie (der Entwickler) einen Fehler gemacht haben und Sie nun die Möglichkeit haben, ihn zu ändern. Ausnahmeklassen werden in Java zur Darstellung von Ausnahmen verwendet, und verschiedene Ausnahmeklassen repräsentieren unterschiedliche Ausnahmen. Aber alle Ausnahmen in Java haben eine Basisklasse namens Exception.
Fehler:
Es handelt sich um ein schwerwiegendes Problem, das durch eine vernünftige Anwendung nicht behoben werden kann. Bei den meisten handelt es sich um Anomalien. Ein Fehler ist ein Fehler der VM (obwohl es sich um einen beliebigen Dienst auf Systemebene handeln kann). Daher ist es schwierig, mit Fehlern umzugehen, und normale Entwickler (natürlich nicht Sie) können mit solchen Fehlern wie Speicherüberlauf nicht umgehen. Fehlerklassen werden wie Ausnahmen zur Darstellung von Fehlern in Java verwendet, und unterschiedliche Fehlerklassen repräsentieren unterschiedliche Fehler. Aber alle Fehler in Java haben eine Basisklasse namens Error.
Zusammenfassend lässt sich sagen, dass der wichtigste Unterschied zwischen Ausnahmen und Fehlern darin besteht, dass Ausnahmen von Entwicklern behandelt werden können, während Fehler systemeigene Natur sind und im Allgemeinen nicht behandelt werden können und auch nicht von unseren Programmierern behandelt werden müssen Behandeln Sie sie.
1. Eine Ausnahme ist ein Ereignis, das während der Ausführung eines Programms auftritt und die Ausführung normaler Anweisungen unterbricht
2. Fehler, eine Aktion oder Instanz, die vom akzeptablen Codeverhalten abweicht
Strukturelle Ausnahmeklassifizierung:
1. Laufzeitausnahme (ungeprüfte Ausnahme)
In Java haben Exception und Error eine gemeinsame übergeordnete Klasse Throwable.
Fehlerausnahme
Mehrere Unterklassen von runtimeException
1. java.lang.ArrayIndexOutOfBoundsExceptionArray-Index-Ausnahme außerhalb der Grenzen. Wird ausgelöst, wenn der Index im Array negativ oder größer oder gleich der Arraygröße ist.
2. java.lang.ArithmeticException
3. java.lang.NullPointerException
des Nullobjekts, Berechnen der Länge des Nullobjekts, Verwenden der Throw-Anweisung zum Auslösen von Null usw.
4 .lang.ClassNotFoundException
wird diese Ausnahme ausgelöst.
Ausnahmebehandlung:
try{}catch{}
try{}catch{}finally{} Der Final-Codeblock wird unabhängig davon ausgeführt, ob eine Ausnahme vorliegt oder nichttry{ }finally{} kann auch in Kombination verwendet werden, Catch{}finally{} jedoch nicht
Hinweis: In der Vererbungsbeziehung überschreibt die Unterklasse die Methode der übergeordneten Klasse und deren Gültigkeitsbereich Das Auslösen von Ausnahmen kann nicht umfassender sein als die der übergeordneten Klasse.
Verwendung von Ausnahmen
Dieser Teil der Verwendung von Ausnahmen ist hauptsächlich Demonstrationscode, auf den wir im Prozess stoßen werden Wenn Sie Code schreiben (natürlich nur einen kleinen Teil), möchten Sie andere inspirieren!
Beispiel 1. Dieses Beispiel demonstriert hauptsächlich den Ausführungsfluss des Codes nach dem Auftreten einer Ausnahme durch den Vergleich zweier Methoden.
public static void testException1() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("异常出现前"); try { System.out.println(ints[4]); System.out.println("我还有幸执行到吗");// 发生异常以后,后面的代码不能被执行 } catch (IndexOutOfBoundsException e) { System.out.println("数组越界错误"); } System.out.println("异常出现后"); } /*output:异常出现前数组越界错误常出现后*/ public static void testException2() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("异常出现前"); System.out.println(ints[4]); System.out.println("我还有幸执行到吗");// 发生异常以后,他后面的代码不能被执行 }
Weisen Sie zunächst auf die Mängel im Beispiel hin. IndexOutofBoundsException ist eine ungeprüfte Ausnahme, daher besteht keine Notwendigkeit, ... zu fangen ..., um die Erfassung anzuzeigen, aber mein Zweck ist es um verschiedene Behandlungsmethoden für dieselbe Ausnahme zu verwenden. Sehen Sie, welchen Unterschied es macht (ich kann es hier nur für eine Weile verwenden). Wenn eine Ausnahme auftritt, springt die erste Methode einfach aus dem Try-Block, der Code dahinter wird jedoch weiterhin ausgeführt. Aber die zweite Art ist anders und springt direkt aus der Methode heraus, die schwieriger ist. Aus der ersten Methode geht hervor, dass try...catch... eine „Transaktionsgarantie“ ist. Ihr Zweck besteht darin, sicherzustellen, dass das Programm unter ungewöhnlichen Umständen abgeschlossen wird Details zum Fehler in den Programminformationen (die Details hängen manchmal vom Design des Programmierers ab).
Beispiel 2. Erneutes Auslösen der Ausnahme
public class Rethrow { public static void readFile(String file) throws FileNotFoundException { try { BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); System.err.println("不知道如何处理该异常或者根本不想处理它,但是不做处理又不合适,这是重新抛出异常交给上一级处理"); //重新抛出异常 throw e; } } public static void printFile(String file) { try { readFile(file); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) { printFile("D:/file"); } }
Die Absicht der Ausnahme ist gut. Versuchen wir, das Programm zu reparieren, aber in Wirklichkeit ist unsere Chance, das Problem zu beheben, sehr gering , wir haben viele Manchmal wird es zum Aufzeichnen von Fehlerinformationen verwendet. Wenn Sie es satt haben, ständig mit Ausnahmen umzugehen, kann das erneute Auslösen von Ausnahmen eine gute Erleichterung für Sie sein. Werfen Sie diese Ausnahme unverändert auf die obere Ebene, an die Person, die diese Methode aufruft, und lassen Sie sie darüber nachdenken. Unter diesem Gesichtspunkt haben uns Java-Ausnahmen (die sich natürlich auf geprüfte Ausnahmen beziehen) viel Ärger bereitet, obwohl der Ausgangspunkt gut ist.
Beispiel 3. Verwendung von Ausnahmekette und Ausnahmeverlust
ExceptionA,ExceptionB,ExceptionC public class ExceptionA extends Exception { public ExceptionA(String str) { super(); } } public class ExceptionB extends ExceptionA { public ExceptionB(String str) { super(str); } } public class ExceptionC extends ExceptionA { public ExceptionC(String str) { super(str); } }
Ausnahmeverlustsituation:
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:19) */
Warum nur ExceptionC wird gedruckt, aber ExceptionB wird nicht gedruckt? Lassen Sie uns das selbst analysieren.
Die obige Situation ist gleichbedeutend mit dem Fehlen einer Ausnahme, was in unserem Fehlerbehebungsprozess sehr nachteilig ist. Was sollten wir also tun, wenn wir auf die obige Situation stoßen? Hier kommt die Ausnahmekette ins Spiel: Speichern Sie die Ausnahmeinformationen und lösen Sie eine weitere Ausnahme aus, ohne die ursprüngliche Ausnahme zu verlieren.
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); //异常连 c.initCause(e); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:21) Caused by: exception.ExceptionB at exception.NeverCaught.f(NeverCaught.java:5) at exception.NeverCaught.g(NeverCaught.java:10) ... 1 more */
Die Merkmale dieser Ausnahmekette werden von allen Ausnahmen gemeinsam genutzt, da die initCause()-Methode von Throwable erbt.
Beispiel 4. Aufräumarbeiten
Aufräumarbeiten sind für uns unerlässlich, da es einige ressourcenintensive Vorgänge wie IO, JDBC gibt. Wenn wir es nicht rechtzeitig nach der Verwendung richtig schließen, sind die Folgen schwerwiegend und führen zu Speicherverlusten. Das Auftreten von Ausnahmen erfordert, dass wir einen Mechanismus entwerfen, damit Ressourcen unabhängig von den Umständen korrekt und zeitnah bereinigt werden können. Das ist endlich.
public void readFile(String file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(file))); // do some other work } catch (FileNotFoundException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
Das Beispiel ist sehr einfach, es ist ein Beispiel für das Lesen einer Datei. Solche Beispiele kommen auch bei JDBC-Operationen sehr häufig vor. (Ich denke also, dass die rechtzeitige und korrekte Bereinigung von Ressourcen eine der Grundqualitäten eines Programmierers ist.)
Versuchen Sie es ... schließlich ist Struktur auch ein Mittel, um sicherzustellen, dass Ressourcen korrekt geschlossen werden. Wenn Sie nicht wissen, welche Ausnahmen während der Codeausführung auftreten, die verhindern, dass Ressourcen bereinigt werden, können Sie versuchen, diesen „verdächtigen“ Code einzuschließen und die Ressourcen dann endgültig zu bereinigen. Geben Sie ein Beispiel:
public void readFile() { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work //close reader reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
Achten wir auf den Unterschied zwischen dieser Methode und der vorherigen Methode. Die nächste Person hat möglicherweise die bessere Angewohnheit, den Leser so früh wie möglich zu schließen. Dies geht jedoch häufig nach hinten los, da Ausnahmen jederzeit vor read.close() auftreten können und eine solche Codestruktur das Auftreten von Ausnahmen nicht verhindern kann. Da das Programm dort abspringt, wo die Ausnahme auftritt, kann der nachfolgende Code nicht ausgeführt werden (dies sollte anhand der obigen Beispiele nachgewiesen werden). Zu diesem Zeitpunkt können wir try...finally verwenden, um Folgendes zu transformieren:
public void readFile() { BufferedReader reader = null; try { try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work // close reader } finally { reader.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
Ressourcen frühzeitig schließen ist ein gutes Verhalten, denn je länger die Zeit, desto größer ist die Wahrscheinlichkeit, dass Sie dies tun vergessen Sie es zu schließen. Auf diese Weise ist die Koordination von try...finally garantiert narrensicher (finde es nicht als problematisch, Java ist so zufriedenstellend).
Lassen Sie uns über eine andere Situation sprechen. Wenn ich eine Datei öffnen oder eine JDBC-Verbindung in der Konstruktormethode erstellen möchte, können wir dies nicht zu Beginn tun, da wir diese Ressource in anderen Methoden verwenden möchten Konstruktormethode. Schließen Sie diese Ressource. Sind wir also ratlos? Die Antwort ist nein. Schauen Sie sich das folgende Beispiel an:
public class ResourceInConstructor { BufferedReader reader = null; public ResourceInConstructor() { try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(""))); } catch (FileNotFoundException e) { e.printStackTrace(); } } public void readFile() { try { while(reader.readLine()!=null) { //do some work } } catch (IOException e) { e.printStackTrace(); } } public void dispose() { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
Dieser Teil geht etwas weiter, aber Ausnahmen scheinen zwar einfach zu verwenden, aber schwierig zu verwenden. Es gibt immer noch viele Dinge in Java müssen gründlich erforscht werden.