目录
一、异常的基本概念
在程序运行过程中出现的错误,称为异常。
二、异常的结构层次
注 : UML是一种统一建模语言,是一种图标式语言(画图的)。UML不是只有java中使用。只要是面向对象的编程语言,都有UML。一般画UML图的都是软件架构师或者说是系统分析师、软件设计人员这些人使用UML。在UML图中可以描述类和类之间的关系,程序执行的流程,对象的状态等。
三、异常的分类
异常主要分为:错误、一般性异常(受控异常)、运行期异常(非受控异常)。
错误:如果应用程序出现了 Error,那么将无法恢复,只能重新启动应用程序,最典型的Error 的异常是:OutOfMemoryError。
受控异常:出现了这种异常必须显示的处理,不显示处理 java 程序将无法编译通过。
非受控异常:此种异常可以不用显示的处理,例如被 0 除异常,java 没有要求我们一定要处理。
四、编译时异常与运行时异常
- 编译时异常发生的概率较高,运行时异常发生的概率较低。
- 编译时异常和运行时异常,都是发生在运行阶段。
- 既然这两种异常都是在运行阶段发生的,编译时异常为什么得此名?
因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。因为异常的发生就是new异常对象。
五、异常处理的两种方式
-
方法声明的位置上,使用throws关键字,抛给上一级。谁调用我,我就抛给谁。抛给上一级。
-
使用try…catch语句进行异常的捕捉。
注意 :异常处理我们一般采用第二种方式,Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生。只有一个结果,终止java程序的执行,而且每一次抛给上一级其同样有这两种处理方式。
六、try…catch详解
- 格式
try {
}catch(OneException e) {
}catch(TwoException e) {
}finally {
}
- 详解
- try 中包含了可能产生异常的代码
- try 后面是 catch,catch 可以有一个或多个,catch 中是需要捕获的异常
- 当 try 中的代码出现异常时,出现异常下面的代码不会执行,马上会跳转到相应的catch 语句块中,如果没有异常不会跳转到 catch 中
- finally 表示,不管是出现异常,还是没有出现异常,finally 里的代码都执行,finally 和 catch可以分开使用,但 finally 必须和 try 一块使用
七、打印异常信息
-
取得异常描述信息 :getMessage()
-
取得异常的堆栈信息(比较适合于程序调试阶段) :printStackTrace()
try {
} catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
八、自动与手动抛异常
- 辨析
① 自动抛出
可以理解为所有没有使用throw关键字的异常处理都是自动抛出,由jvm进行判断和抛出。
②手动抛出
throw + 异常类的对象
- throw与throws的区别
throw : 将产生的异常抛出(强调的是动作),抛出的既可以是异常的引用,也可以是异常对象。(位置: 方法体内)
throws : 如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。用它修饰的方法向调用者表明该方法可能会抛出异常(可以是一种类型,也可以是多种类型,用逗号隔开)(位置: 写在方法名 或方法名列表之后 ,在方法体之前。)
九、异常的捕获顺序
异常的捕获顺序应该是由小到大
try {
FileInputStream fis = new FileInputStream("test.txt");
fis.close();
}catch(IOException e) {
e.printStackTrace();
}catch(FileNotFoundException e) {
e.printStackTrace();
}
//将 IOException 放到前面,会出现编译问题
//因为 IOException 是 FileNotFoundException 的父类,
//所以截获了 IOException 异常后,IOException 的子异常
//都不会执行到,所以再次截获 FileNotFoundException 没有任何意义
//异常的截获一般按照由小到大的顺序,也就是先截获子异常,再截获父异常
十、自定义异常
- 概述
因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。在Java中要想创建自定义异常,需要继承Throwable或者他的子类Exception,因为异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性,这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。
- 语法格式
class 自定义异常类 extends 异常类型(Exception){
// 因为父类已经把异常信息的操作都完成了,所在子类只要在构造时,将异常信息传递给父类通过super 语句即可。
// 重写 有参 和 无参 构造方法
}
十一、方法覆盖与异常
子类方法不能抛出比父类方法更多的异常,但可以抛出父类方法异常的子异常。