Java------异常处理机制,
一、什么是异常处理
异常处理从字面的意思来讲就是一种发生在 java 程序中的错误并对其处理,但对程序员而言,异常的处理不单单的简单去处理异常,就 ok 了,还有众多的概念和使用异常的方式方法需要掌握
异常在 java 中分有三种:
1、编译时异常(受检异常)------> 这种异常发生的概率很高;
2、运行时异常 ------> 这种异常发生的概率较低,发生时直接退出 JVM;
3、错误(error)-----> 错误和异常是不同,错误其实是脱离了程序员控制的问题,错误在代码中经常被忽略。比如内存溢出,在编译过程也是发现不了的;

如上图可以看出受检异常与运行时异常都继承于 Exception 类, 而 Exception 与 Error 继承 Throwable 类,最终它们的父类都是 Object;
二、处理异常的方式有哪些
处理异常的方式有两种:
1、throws <上抛>:在需要进行异常处理的方法体上加上 <throws 异常列表>,该方法体的异常将不会被本方法进行处理,如果谁调用该方法,则调用该方法的同时将异常一起调用。当然调用该方法的方法可以进行处理该异常,也可以使用被调用的方法一样的方式对异常进行抛出。
这样的操作其实只是将异常交给了其他的程序处理,如果其他程序没有能力进行处理,则将一直进行抛出,直到遇见一个能够处理该异常的程序,并终止异常(该如何处理该异常呢?);
通过一个程序来更深次的了解 throws 如何处理异常:

1 1
import java.io.FileInputStream;
2 2
import java.io.FileNotFoundException;
3 3
4 4
/**
5 5 * throws 的深层次理解
6 6 */
7 7
public class Test17 {
8 8
9 9
// public static void main(String[] args) throws FileNotFoundException{ // 当然这里也可以直接使用父类 Exception
10 10
11 11
public static void main(String[] args)
throws Exception{
12 12
13 13 System.out.println("我是入口"
);
14 14
15 15
m1();
16 16
}
17 17
18 18
public static void m1()
throws FileNotFoundException{
19 19
// 从m1 - m3 的调用可以看出 throws 处理机制是不对异常处理,只是抛出异常,谁调用该异常,谁处理,最终会流向哪里处理呢?
20 20
21 21 System.out.println("m1...start!"
);
22 22 m2();
// m1() 也同样出现了异常
23 23 System.out.println("m1...end!"
);
24 24
}
25 25
26 26
public static void m2()
throws FileNotFoundException{
27 27
//
28 28
29 29 System.out.println("m2...start!"
);
30 30 m3();
// 从这个地方我们就可以看出了当 m2()进行调用 m3()时,m2() 方法体也出现需要处理的异常
31 31
// 同样的可以依照 m3() 方法进行处理
32 32
33 33 System.out.println("m2...end!"
);
34 34
}
35 35
36 36
// public static void m3() throws NullPointerException{
37 37
// 已经对该方法体进行了抛出异常的设置,为什么是无效的?
38 38
// NullPointerException 因为这个是一个空指针的异常,它不对 IO 流的异常进行处理
39 39
40 40
public static void m3()
throws FileNotFoundException {
41 41
// FileNotFoundException 异常机制对 m3 起到了效果,主要因为 FileNotFoundException 继承 IOException;
42 42
43 43 FileInputStream fis =
new FileInputStream("E:\\jaa 作业室\\temp.java"
);
44 44
// FileInputStream 是一个继承了异常基本类的 IO 流; 所以同样在使用它的时候程序员就需要对它进行处理
45 45
46 46 System.out.println("m3...end!"
);
47 47
}
48 48
}
49 49
/** 看看如果读取的路径出现错误会发生什么结果吧
50 50 * 我是入口
51 51 * m1...start!
52 52 * m2...start!
53 53 * // 这里也出现一了一件有意思的事情:
54 54 * // 每个方法体中只有在 异常 前的值被输出,紧跟异常之后的值直接不被读取了
55 55 * // 从中得出一个结论: 一个方法中通过 throws 抛出的异常,在被调用时,调用者与被调用本身,异常之后的代码将被执行中断,不会输出结果,异常前的值会进行输出
56 56 *
57 57 *
58 58 * Exception in thread "main" java.io.FileNotFoundException: E:\jaa 作业室\temp.java (系统找不到指定的路径。)
59 59 * // 这里就是异常的处理结果了: Exception in thread "main" java.io.FileNotFoundException: E:\jaa 作业室\temp.java (系统找不到指定的路径。)
60 60 * // 是不是发现奇妙的事情:各个方法体不断的对异常抛出,最后在 main 方法中进行了异常处理,那为什么方法体中就不能处理,只能在 main 中处理呢?
61 61 * // 其实 main 方法是主调方法,是一切程序的入口,方法体只有被 main 调用才能输出结果,(当然后面还有一种方法可以在方法体中处理)而异常的处理其实
62 62 * // 也不是在 main 方法中处理的,可以看到 main 方法体上也出现了抛出异常的设置, 其实在程序员不能看到的 JVM 中,程序将异常最终交给了
63 63 * // FileNotFoundException 类处理该异常。
64 64 *
65 65 *
66 66 * at java.base/java.io.FileInputStream.open0(Native Method)
67 67 * at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
68 68 * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
69 69 * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
70 70 *
71 71 * at Rview.Test17.m3(Test17.java:43)
72 72 * at Rview.Test17.m2(Test17.java:30)
73 73 * at Rview.Test17.m1(Test17.java:22)
74 74 * at Rview.Test17.main(Test17.java:15)
75 75 * // 这里表示的是异常出现的行号索引
76 76 */
Throws 深层次理解
2、try...catch... <捕捉,处理异常>: 捕捉有可能发生异常的代码,并将它处理,不会对异常抛出,只会终止异常的向后发展
通过一个程序来了解 try...catch... 如何处理异常:

1 1
import java.io.FileInputStream;
2 2
import java.io.FileNotFoundException;
3 3
import java.io.FileOutputStream;
4 4
import java.io.IOException;
5 5
6 6
/**
7 7 * try...catch... 的使用方法和重点
8 8 */
9 9
10 10
// 这是一个与 Test17 相同的程序,但我们需要对这个程序使用使用不同的异常处理机制
11 11
12 12
public class Test18 {
13 13
14 14
public static void main(String[] args) {
15 15
16 16
m1();
17 17
}
18 18
19 19
public static void m1(){
20 20
21 21 System.out.println("m1...start!"
);
22 22
m2();
23 23 System.out.println("m1...end!"
);
24 24
}
25 25
26 26
public static void m2(){
27 27
28 28 System.out.println("m2...start!"
);
29 29
m3();
30 30 System.out.println("m2...end!"
);
31 31
}
32 32
33 33
34 34
35 35
public static void m3(){
36 36
37 37
38 38
// try...catch... 的重点: 可以在发生异常点进行直接处理异常,当其他调用者调用时将不会发现该方法曾经有过异常的情况,同时也不会将异常感染
39 39
// 给调用者,总之可以直接对异常直接处理
40 40
41 41
// try...catch...不仅仅只能对单个异常进行捕捉处理,同时可以对多个不同类型的异常进行处理
42 42
try {
43 43 FileInputStream fis =
new FileInputStream("E:\\java\\作业室\\temp.java"
);
44 44
// try 中将可能发生异常的代码段进行捕捉
45 45 fis.close();
// 再次出现了一个异常,再处理
46 46
47 47
// 以上代码出现异常,直接进入 catch 分支,不对其后的代码进行编译;
48 48 System.out.println("hello "
);
49 49
}
50 50
catch (FileNotFoundException e
/*必须要加变量名*/) {
/*将捕捉到的异常进行处理*/
51 51
52 52
// e.printStackTrace(); // 显示处理结果的方法
53 53
54 54 System.out.println("出现了异常,已经处理!!"
);
55 55
56 56 }
catch (IOException e){
57 57
// 已经进行了异常处理,为什么出现了错误?
58 58
// 两个 catch 对不同的异常进行了处理,但是,前一个 catch 的异常处理类是最高类 Exception,而后一个 catch 的异常处理类
59 59
// FileNotFoundException 是 Exception 的一个子类,所以在进行多次的 catch 异常处理时注意子类与父类的位置关系
60 60
//(子类在前、父类在后 或者 同时是子类)
61 61
e.printStackTrace();
62 62
}
63 63
// 同样要进行异常处理,这次我们将使用 try... catch... 的方式处理
64 64
65 65 System.out.println("m3...end!"
);
66 66
}
67 67
}
68 68
69 69
/** output result:
70 70 * m1...start!
71 71 * m2...start!
72 72 * m3...end!
73 73 * // 奇妙的事情又发生了,使用 try... catch...的方式处理异常并不影响异常之后的代码运行
74 74 *
75 75 * m2...end!
76 76 * m1...end!
77 77 *
78 78 *
79 79 * java.io.FileNotFoundException: E:\java\作业室\temp.java (系统找不到指定的路径。)
80 80 * // 这个结果的输出靠 printStackTrace() 方法;
81 81 *
82 82 * at java.base/java.io.FileInputStream.open0(Native Method)
83 83 * at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
84 84 * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
85 85 * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
86 86 *
87 87 *
88 88 * at Rview.Test18.m3(Test18.java:42)
89 89 * at Rview.Test18.m2(Test18.java:30)
90 90 * at Rview.Test18.m1(Test18.java:23)
91 91 * at Rview.Test18.main(Test18.java:17)
92 92 * // 同样是异常出现所在的行号索引
93 93 */
try...catch 处理方式
用户点评