一、导言
当学习完前面的知识,我们能够写一些简单的功能性的软件了,对于数据的输出,可以使用系统的标准输出打印。但是当我们碰到一些特殊情况,如:
//定义了一个数组
int[] i = new int[3]
//输出不存在的元素
System.out.print(i[3]);
这样编译时是没有语法错误的,但是当运行时,会找不到数组角标为3的元素。那么这就是一个异常行为。
从上面这个例子,我们不能100%的确认我们编写的程序是正确的。或者说不能确认程序运行时与我们预想的一致。那么当这种不一致出现时,就需要异常处理机制。
不仅仅是在Java中,Python,C++等常用语言都有异常处理机制。
下面来看看Java中的异常处理机制。
二、异常体系结构
- java.lang.Trowable
- Error:错误,程序中不进行处理
- Exception:异常:编写程序时,就要考虑到这些异常的处理
- 编译时异常(执行javac.exe时)
- 运行时异常(执行时出现异常),后面的代码不再执行
- 运行时常见异常:
- 数组下标越界:ArrayIndexOutOfBoundsException
- 算数异常:ArithmeticException
- 类型转换异常:ClassCastException
- 空指针异常:NullPointerException
- 运行时常见异常:
三、如何处理(异常处理的抓抛模型)
3.1. 抛
执行代码时,一旦出现异常,就会在异常的代码处生成一个对应的异常类型的对象,并将此对象抛出(自动抛出/手动抛出)。
- 一但抛出,程序终止执行
- 此异常类的对象抛给方法的调用者
- 手动抛出:throw new ArithmeticException();
3.2 抓
抓住上一步抛出来的异常类的对象,如何抓:
java提供两种方式来处理一个异常类的对象
3.2.1 方式一:自己处理
try{
//可能出现异常的代码
}catch(Exception1 ex1){
//处理方式一
}catch(Exception2 ex2){
//处理方式二
}finally{
//一定要执行的代码
}
//注:
//try内声明的变量类似于局部变量
//finally是可选的
//catch里面可以有两种处理方式:e.getMessage();e.printStackTrace();
//可以有多个catch语句,顺序执行一次
//处理了异常,其后代码可继续执行
//try-catch可以相互嵌套
//如果catch是包含关系,则子类放上面,父类放下面。即先处理精确的,再处理粗略的。
//finally语句一定会被执行,不管try,catch中是否有异常未处理,或return语句。
3.2.2 方式二:往上抛 throws
交给方法的调用者去处理,例如在读写IO流时会需要显式处理调用可能产生异常的方法可能抛出的异常。
四、自定义异常
仿照一个异常来写:
public class MyException extends RuntimeException{
static final long serialVersionUID=-87878787;
public MyException(){
super();
}
public MyException(String msg){
//异常携带的Message
super(msg);
}
}