异常处理2

273 阅读6分钟

异常处理

复习

什么是异常

所谓的“异常”是在Java程序当中出现的一种不正常的情况,但是又有别于“报红线”。

在编译期,大部分报红线是“语法错误”;只有出现“未处理的异常 某某Exception”才属于Java中单独规范的“异常”内容。

在运行期,出现异常信息的打印效果,并终止掉我们的程序运行,那么这里也是发生了异常。异常打印效果如下:

Exception in Thread “main” 异常类的限定名:异常的详细信息

at 异常发生的位置(某篇.java:行)

at 异常发生的位置(某篇.java:行)

at 异常发生的位置(某篇.java:行)

at 异常发生的位置(某篇.java:行)

at 异常发生的位置(某篇.java:行)

异常的分类

对于我们来说,异常是Java当中专门为针对各种可能出现的不正常情况设计的一整套Java类。它们呈现出了一种继承结构。

Throwable

Exception Error

RuntimeException 其他

区分:

1、Exception 和 Error

2、运行时异常 和 编译时异常

运行时异常 在编译期是不会报的,而是在运行期执行的时候发生。 编译时异常 在编译期就会提示我们这里(方法调用处),有可能出现异常,必须先有处理方案,然后才能编译通过。

运行时异常一旦发生,代码中又没有处理方案,那么会终止程序的执行。

编译时异常是希望我们在编写的时候就提供解决方案,否则根本不能运行。

异常的传播机制

当JVM在运行过程中,一旦发现这里出现异常情况,那么就会主动根据当前异常情况产生对应的异常类对象。然后执行异常的处理方案,如果当前位置没有处理,那么JVM就会结束本方法,然后根据方法调用栈流程转到方法调用处。然后继续查看这里有没有该异常类的解决方案,如果还是没有,那就继续往上传播。

如果整个代码都没有该异常的解决方案,那么最终的效果就是一定来到main方法检查是否解决。如果还是没有,那么会同样终止main方法的执行。而main方法被终止,代表着程序被结束,然后JVM在关闭前就会把异常信息打印在控制台。

关联知识点:打印异常信息,是调用异常父类Throwable当中的printStackTrace()。

异常的处理方案

出现异常不可怕,解决就行。

事前处理

这种处理方案就是让异常根本不发生。在我们写代码的时候就提前把异常出现的可能给解决掉。

几乎所有的运行时异常,都应该采用这种提前做if判断的方式来解决。

只是由于现在我们学到的内容不足,导致有些能够提前解决的手段不足,因此在目前的练习和讲解中采用了事后处理的方案。

事后处理

自己处理(try-catch-finally)

try{}的任务是书写正常逻辑的代码(当然也是有可能发生异常的代码块),我们试着让他执行。

catch(){}的任务是捕获异常,并且书写捕获后要执行的处理动作。注意:就算{}中不写代码,也算把异常捕获了。

finally{}的任务是书写不管是否发生异常都要执行的动作,通常是“资源清理”,“管道关闭”,“连接的断开”......

组合上:

1、try-catch

2、try-catch-finally

3、try-finally

我们需要清楚它们三者执行的流程:

  1. 发生异常 -- try块会从发生异常的代码行跳转,然后用异常对象依次匹配每一个catch块当中声明的捕获类型。“依次”和“每一个”说明:一个try后面可以有多个catch,多个catch是有顺序的(有继承关系的异常,要先写子后写父)。

匹配上了,就进入该catch块执行。

补充了一个JDK7的语法:一个catch块可以用"|"声明捕获多种异常类。

执行完catch块以后就进入finally块执行,然后异常处理的流程结束。

  1. 没有发生异常:try块里面的代码会全部执行,然后进入finally块,最后异常处理流程结束。

考察点:

a. try-catch-finally的流程

b. catch块的特点,包括可不可以写多个,有没有顺序.......

c. finally的特点,包括执行顺序,能不能阻止,相似关键词的分辨final和finalize,如果try或catch当中有return,那么fianlly在return 之前还是之后?

交给上层处理(throw throws)

throw 书写在方法的实现体当中是一条执行指令,代表当这条指令执行的时候真的会发生一个异常对象的抛出。 throw后面跟的是一个异常对象。

throws 书写在方法声明的最后,表示本方法有可能抛出某些类型的异常。 它的后面跟的是异常类的名字。

两个的关联是:如果在一个方法的内部throw了一个编译时异常对象,那么就要求该方法的声明处必须要有throws。

关联知识点:

  1. 一个完整的方法声明:

修饰符 返回类型 方法名(形参列表) throws 异常类

  1. 方法重写的规范被增加条件了

2-1、方法名保持一致;

2-2、参数列表保持一致;

2-3、返回类型保持一致;

2-4、访问修饰符重写后不能比重写前小

2-5、重写后不能比重写前抛出更多的异常,这里的更多指的是范围,不是个数。

如何选择自己处理还是往上抛

选择的依据是:看这个异常引起的原因,是当前方法本身引起的那么肯定是当前方法自己处理;如果是上层调用者引起的,就应该抛上去,让调用者处理。

自定义异常

场景:虽然在Java的内库当中,设计了很多异常类,应对各种情况。但是,还是有很多场景中有与业务内容相关的异常,是它不可能涉及到的。所以,这种情况下,我们就需要自定义异常了。

语法

1、让类继承于Exception或它的某个子类;

2、给这个类增加带参构造

3、还可以给这个异常增加一些工具方法,比如:日志的书写。