Java进阶教程:异常处理
前往不要以为懂try...catch..finally就懂异常了!
异常
什么是异常
异常简单理解就是程序运行出现问题了,好比一个人生病了,既然时生病了,那对于我们个人来说,有些可以治愈,有些是绝症。对于可以治愈的病呢,我们可以采取一些补救措施来维持健康,比如吃药、打针、做手术等等,这些措施呢就是异常处理了。对于绝症呢,我们只能听天由命了,大概率情况下等待死亡。这两类病呢对应Java异常体系中的异常和错误,我们来看一下!
Java异常体系
Throwable:Java语言中所有错误和异常的超类,一切可以抛出的东西都是基于此。
Error:代指严重问题,大到程序无法处理,只能人工介入。
StackOverflowError
OutOfMemoryError
Exception:
CheckedException:检查性异常,例如IO异常/SQL异常,特点不管你愿不愿意,都需要写try...catch进行处理。
UncheckedException:也称运行时异常,出现这种异常时由Java虚拟机接管,异常由系统一层一层向上抛,直到遇到处理代码。如果没有遇到,直到到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。
注意:层级关系表示继承。
我们再举个简单例子来说明一下检查异常和运行时异常。
注意:所有的运行时异常都继承自RuntimeException。
Java异常处理
对于错误呢,我们无力回天,但是对于捕获到的异常可以进行处理,来做好补偿机制,以防止线程被中断。
这个处理呢是两层意思,第一种就是我们自己处理,第二种就是让调用者处理。对于自己处理,我们写好try...catch...就好,对于让调用者处理,我们把这个异常抛出就好。
//自己处理,使用try...catch...
public void handle() {
try {
File file = new File("./a.txt");
if (file.exists()) {
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//抛出去,让调用者处理
public void unhandle() throws IOException {
File file = new File("./a.txt");
if (file.exists()) {
file.createNewFile();
}
}
这里有一个坑,使用throw抛出异常时,对于运行时异常,你不必在方法后面声明throws RuntimeException,但是对于检查型异常,除了方法内throw,方法上也必须声明throw 待抛出的异常,如下:
//运行时异常
public void unChecked(){
try{
System.out.println(5/0);
}catch (RuntimeException e){
throw e;
}
}
//检查型异常
public void checked() throws IOException {
try {
FileInputStream fileInputStream = new FileInputStream(new File("./a.txt"));
fileInputStream.close();
} catch (Exception e) {
throw e;
}
}
到这里我们再来简单总结一下:
异常处理有两种方案:
自己处理:
运行时异常可以不处理,也可以进行捕获处理
检查型异常不处理编译不过
抛给调用者:
运行时异常可以不处理,一旦发生默认抛出去
检查型异常如果执意抛出,必须声明throws和调用throw方法。
异常处理设计
只有在必须使用异常的地方才使用异常,不要用异常去控制程序的流程。
切忌使用空catch块。
检查异常和非检查异常的选择
注意catch块的顺序
异常处理尽量放在高层进行
在finally中释放资源
参考资料