Heim  >  Artikel  >  Java  >  Grundkenntnisse der Java-Ausnahme- und Fehlerbehandlung

Grundkenntnisse der Java-Ausnahme- und Fehlerbehandlung

高洛峰
高洛峰Original
2017-01-18 14:46:311455Durchsuche

Ausnahmen und Fehler:
Ausnahmen: Programmfehler in Java sind hauptsächlich Syntaxfehler und semantische Fehler, die beim Kompilieren und Ausführen eines Programms auftreten, werden zusammenfassend als Ausnahmen bezeichnet und sind VM (Virtual Machine). Dabei teilt Ihnen die VM mit, dass Sie (der Entwickler) einen Fehler gemacht haben und nun die Möglichkeit haben, ihn zu beheben. 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 Ausfall der VM (obwohl es sich um einen beliebigen Dienst auf Systemebene handeln kann). Daher sind Fehler schwer zu behandeln, und der durchschnittliche Entwickler (natürlich nicht Sie) kann mit diesen Fehlern, wie z. B. einem 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 systembedingt sind und im Allgemeinen nicht behandelt werden können und nicht von unseren Programmierern behandelt werden müssen.
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
Außergewöhnliche strukturelle Klassifizierung:
1. Laufzeitausnahme (ungeprüfte Ausnahme)
2. Kompilierungszeitausnahme (geprüfte Ausnahme)
Die laufende Ausnahme ist RuntimeException; der Rest sind alle Kompilierungsausnahmen
in Java. Ausnahme und Fehler Fehler haben eine gemeinsame übergeordnete Klasse Wurfbar.
Fehlerausnahme
Mehrere Unterklassen von runtimeException
1. java.lang.ArrayIndexOutOfBoundsException
Array-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
Arithmetische Bedingungsausnahme. Zum Beispiel: Ganzzahldivision durch Null usw.
3. java.lang.NullPointerException
Nullzeiger-Ausnahme. Diese Ausnahme wird ausgelöst, wenn die Anwendung versucht, null zu verwenden, wenn ein Objekt erforderlich ist. Zum Beispiel: Aufrufen der Instanzmethode des Nullobjekts, Zugriff auf das Attribut
des Nullobjekts, Berechnen der Länge des Nullobjekts, Verwenden der Throw-Anweisung zum Auslösen von Null usw.
4. ClassNotFoundException
Klassenausnahme nicht gefunden. Wenn die Anwendung versucht, eine Klasse basierend auf einem Klassennamen in Zeichenfolgenform zu erstellen, aber nach dem Durchlaufen von CLASSPAH die Klassendatei mit dem entsprechenden Namen nicht finden kann,
wird diese Ausnahme ausgelöst.
Ausnahmebehandlung:
try{}catch{}
try{}catch{}finally{} Der finale Codeblock wird unabhängig davon ausgeführt, ob eine Ausnahme vorliegt oder nicht
try{}finally {} ist ebenfalls möglich. Es kann in Kombination verwendet werden, aber Catch{}finally{} kann nicht verwendet werden
Hinweis: In der Vererbungsbeziehung überschreibt die Unterklasse die Methode der übergeordneten Klasse und der Umfang der ausgelösten Ausnahmen kann nicht größer sein als die übergeordnete Klasse

Verwendung von Ausnahmen
Dieser Teil der Verwendung von Ausnahmen ist hauptsächlich Demonstrationscode, auf den wir beim Schreiben von Code stoßen werden (natürlich nur ein kleiner Teil). um andere zu 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 ist es nicht erforderlich, ... zu fangen ..., um die Erfassung anzuzeigen, aber mein Zweck ist es Um verschiedene Methoden für dieselbe Ausnahme zu verwenden, sehen Sie, welchen Unterschied sie haben und welches Ergebnis sie haben (hier kann ich sie 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 „Transaktions“-Garantie ist. Ihr Zweck besteht darin, sicherzustellen, dass die Ausführung des Programms unter ungewöhnlichen Umständen abgeschlossen wird, und sie benachrichtigt den Programmierer außerdem über detaillierte Informationen der Fehler (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 die Chance, dass wir es reparieren, sehr gering, was wir oft nutzen es, um Fehlermeldungen aufzuzeichnen. 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 wird nur ExceptionC gedruckt, aber nicht ExceptionB Wolltuch? Lassen Sie uns das selbst analysieren!
Die obige Situation entspricht dem Fehlen einer Ausnahme, was für unseren Fehlerbehebungsprozess sehr nachteilig ist. Was sollten wir also tun, wenn wir auf die obige Situation stoßen? Hier kommt die Ausnahmeverkettung ins Spiel: Sie speichert Ausnahmeinformationen, sodass Sie eine weitere Ausnahme auslösen können, 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
*/

这个异常链的特性是所有异常均具备的,因为这个initCause()方法是从Throwable继承的。
例4. 清理工作
清理工作对于我们来说是必不可少的,因为如果一些消耗资源的操作,比如IO,JDBC。如果我们用完以后没有及时正确的关闭,那后果会很严重,这意味着内存泄露。异常的出现要求我们必须设计一种机制不论什么情况下,资源都能及时正确的清理。这就是finally。

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();
}
}
}

例子非常的简单,是一个读取文件的例子。这样的例子在JDBC操作中也非常的常见。(所以,我觉得对于资源的及时正确清理是一个程序员的基本素质之一。)
Try...finally结构也是保证资源正确关闭的一个手段。如果你不清楚代码执行过程中会发生什么异常情况会导致资源不能得到清理,那么你就用try对这段"可疑"代码进行包装,然后在finally中进行资源的清理。举一个例子:

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();
} 
}

我们注意一下这个方法和上一个方法的区别,下一个人可能习惯更好一点,及早的关闭reader。但是往往事与愿违,因为在reader.close()以前异常随时可能发生,这样的代码结构不能预防任何异常的出现。因为程序会在异常出现的地方跳出,后面的代码不能执行(这在上面应经用实例证明过)。这时我们就可以用try...finally来改造:

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();
}
}

及早的关闭资源是一种良好的行为,因为时间越长你忘记关闭的可能性越大。这样在配合上try...finally就保证万无一失了(不要嫌麻烦,java就是这么中规中矩)。
再说一种情况,假如我想在构造方法中打开一个文件或者创建一个JDBC连接,因为我们要在其他的方法中使用这个资源,所以不能在构造方法中及早的将这个资源关闭。那我们是不是就没辙了呢?答案是否定的。看一下下面的例子:

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();
}
}
}

这一部分讲的多了一点,但是异常确实是看起来容易用起来难的东西呀,java中还是有好多的东西需要深挖的

更多java异常与错误处理基本知识相关文章请关注PHP中文网!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn