- 1.什么是异常?
- 2.异常体系
- 3.Error
- 4.Exception
- 4.1.编译时异常
- 4.2.RuntimeException
- 5.编译时异常的处理机制
- 5.1.throws
- 5.2.try...catch
- 5.3.throws和try...catch结合
- 6.总结
异常是程序在执行的过程中出现的错误。
2.异常体系 3.Error系统级别异常,出现异常后无法通过程序本身解决的异常,只能重启应用程序。
4.Exception异常出现后通过程序本身就能解决的异常。
4.1.编译时异常除了RuntimeException外的异常都是编译异常,它是源码编译前需要处理的异常。
必须明确的一点,编译时异常不是指编译时出现的异常,而是指编译前需要处理的异常,它和所有异常一样都是程序在运行期间出现的错误。
针对某些代码,如果在编译前不进行异常处理,那么就无法通过编译器生成字节码文件。这就是所谓的异常处理,异常处理方式会在稍后进行讲解。
异常处理工作是程序员不得不做的,即使后来程序在运行时没有出现异常。我猜设计师当初这样设计是因为某些代码会经常出现错误,所以必须提前应对。
当程序在JVM运行时真的出现这种异常,就会根据之前的异常处理方案去处理异常。
编译异常和程序员的开发水平和没有一点关系,程序员无法制造编译异常,它往往是因为用户的错误输入导致的异常,比如找不到文件。
编译时异常是可遇而不可求的。
常见的编译异常:
OException:输入输出流异常
FileNotFoundException:文件找不到的异常
ClassNotFoundException:类找不到的异常
DataFormatException:数据格式化异常
NoSuchFieldException:没有匹配的属性异常
NoSuchMethodException:没有匹配的方法异常
SQLException:数据库操作异常
TimeoutException:执行超时异常
运行时异常,它是源码编译前不需处理的异常。
如果出现了RuntimeException,那就表示代码设计的逻辑不够严谨,这就是程序员本身的问题了。
常见的运行时异常:
NullPointerException:空指针异常
ArrayIndexOutofBoundsException:数组越界异
ClassCastException:类型转换异常
IllegalArgumentException:非法的参数异常
InputMismatchException:输入不匹配
异常处理机制有三种,分别是:
- throws:将方法出现的异常抛给方法调用者,层层往外抛,最终抛给JVM,由JVM出手杀死程序。异常处之前的代码都会执行,异常处之后的代码不会执行。
- try…catch:将方法出现的异常进行捕捉处理,异常处之前和之后的代码正常执行。
- throws和try…catch相结合:将需要处理的异常的方法都用throws抛给调用者,层层往外抛,在最外层的调用者进行try…catch统一捕捉异常。
下面通过代码运行实践验证结论:
5.1.throws代码演示:
//将异常抛给JVM
public static void main(String[] args) throws FileNotFoundException {
f2();
}
//将异常抛给方法调用者main()
public static void f2() throws FileNotFoundException {
f1();
System.out.println("f2...");
}
//将异常抛给方法调用者f2()
public static void f1() throws FileNotFoundException {
System.out.println("test throws");
InputStream is = new FileInputStream("e:\2\abc.txt");
System.out.println("f1...");
}
测试结果:
由测试结果可以看出,异常出现处即InputStream is = new FileInputStream(“e:2abc.txt”),在它之前的代码都运行了,并立即杀死程序,打印异常的日志信息,在异常处之后的代码明显没有执行。
5.2.try…catch代码演示:
public static void main(String[] args) {
f2();
}
//自己捕捉异常
public static void f2() {
f1();
try {
InputStream is = new FileInputStream("e:\2\abc.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("f2...");
}
//自己捕捉异常
public static void f1() {
System.out.println("test throws");
try {
InputStream is = new FileInputStream("e:\2\abc.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("f1...");
}
测试结果:
可以从输出内容看出,异常处之前的代码和之后的代码都被执行了。
关于这个异常处的定义,可要仔细说说了,在throws异常处理机制中,异常处就是出现异常的那一行代码。
可是它在try…catch里的定义可完全和throws的不一样:
在try…catch中异常处是try里面出现异常的那一行及其往后的内容。
try这个关键字可不简单,它会让JVM将出现异常的那一行及其往后的内容看作是一个整体异常处。
请往下看:
public static void main(String[] args) {
f2();
}
//自己捕捉异常
public static void f2() {
f1();
try {
InputStream is = new FileInputStream("e:\2\abc.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("f2...");
}
//自己捕捉异常
public static void f1() {
System.out.println("test throws");
try {
int a = 10,b = 20;
System.out.println("a:" + a);
System.out.println("b:" + b);
InputStream is = new FileInputStream("e:\2\abc.txt");
System.out.println(sum(a, b));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("f1...");
}
public static int sum(int a, int b) {
return a + b;
}
测试结果:
从输出的内容可以看出,a和b被输出了,但并没有执行sum(),这是为何?
因为a和b在异常出现的那一行(即InputStream这行)之前,而sum()这一行在InputStream这行之后,JVM认为InputStream这行和及其往后的行是一个整体异常处,所以就不往下执行sum()方法了。
所以我们不要盲目地像别人那样把将所有代码都放在try里面,要谨慎考虑啊。
那什么时候把代码都放进try里面?什么时候又不全放里面了?
答:如果出现异常的那一行代码会影响其在try里它往后的代码,那就都代码放进try里面,因为要保持程序的一致性嘛。相反,出现异常的那一行代码不会影响它往后的代码,那就不要都放进try里,都放进去,你的异常不就连累我其他代码的正常运行吗?
5.3.throws和try…catch结合代码演示:
public static void main(String[] args) {
try {
f2();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//自己捕捉异常
public static void f2() throws FileNotFoundException {
f1();
InputStream is = new FileInputStream("e:\2\abc.txt");
System.out.println("f2...");
}
//自己捕捉异常
public static void f1() throws FileNotFoundException {
System.out.println("test throws");
InputStream is = new FileInputStream("e:\2\abc.txt");
System.out.println("f1...");
}
throws和try…catch相结合,可以省去重复的try…catch工作,将所有异常集中处理,让程序员开发起来变得十分方便。
6.总结异常是什么?
异常是程序执行中出现的错误。
异常的分类?
- Errror:系统级别的错误,异常出现后程序本身无法处理,需要重启应用程序。
- Exception:java.lang包下的异常,异常出现后程序本身就能解决的异常。
- RuntimeException:运行时异常,源码编译前不需要进行处理的异常。
- 编译时异常:源码编译前需要进行处理的异常,否则无法通过编译。
编译时异常处理机制有几种?
- throws:将方法的异常抛给方法的调用者,层层往外抛,直至抛给JVM,让JVM杀死程序,异常处之前的代码都会执行,异常处之后的代码不会执行。
- try…catch:将方法的异常进行捕捉处理,异常处之前的代码和异常处之后的代码都会正常执行。
- throws和try…catch结合:将需要处理的异常用throws抛给方法调用者,层层往外抛,在外层的方法调用者中统一用try…catch捕捉处理异常。
需要注意的点:
异常处在throws和try…catch种的定义不一样,在throws里,异常处就是异常出现的那一行,而在try…catch中,异常处是try里异常出现的那一行及其它往后的代码。
三种异常处理机制的比较:
throws是一种不负责任的行为,层层往外抛,最终把“麻烦”抛给虚拟机,运行完程序异常处之前的代码就杀死程序,异常处往后的代码都不会执行。
try…catch是程序自身处理错误,是一种负责任的行为,而且异常处往后的代码也能继续执行,直至程序执行完毕。但是不好的一点是,当方法嵌套过多时,可能有多个方法需要try…catch,非常麻烦。
如果前提是出现异常的那一行代码会影响其在try里它往后的代码,throws和try…catch相结合这种异常处理方案是最优选择,因为它将所有异常都抛给了最外层调用者去统一处理,能为程序员省去不少时间和精力。



