Java进阶教程:异常处理
Java进阶教程:异常处理
前往不要以为懂try...catch..finally就懂异常了!
异常
什么是异常
异常简单理解就是程序运行出现问题了,好比一个人生病了,既然时生病了,那对于我们个人来说,有些可以治愈,有些是绝症。对于可以治愈的病呢,我们可以采取一些补救措施来维持健康,比如吃药、打针、做手术等等,这些措施呢就是异常处理了。对于绝症呢,我们只能听天由命了,大概率情况下等待死亡。这两类病呢对应Java异常体系中的异常和错误,我们来看一下!
Java异常体系
- Throwable:Java语言中所有错误和异常的超类,一切可以抛出的东西都是基于此。
- Error:代指严重问题,大到程序无法处理,只能人工介入。
- StackOverflowError
- OutOfMemoryError
- Exception:
- CheckedException:检查性异常,例如IO异常/SQL异常,特点不管你愿不愿意,都需要写try...catch进行处理。
- UncheckedException:也称运行时异常,出现这种异常时由Java虚拟机接管,异常由系统一层一层向上抛,直到遇到处理代码。如果没有遇到,直到到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。
- Error:代指严重问题,大到程序无法处理,只能人工介入。
注意:层级关系表示继承。
我们再举个简单例子来说明一下检查异常和运行时异常。
注意:所有的运行时异常都继承自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中释放资源