1.什么是异常
在Java程序运行时,常常会发生一些非正常的情况,这种情况称之为异常。根据性质可以分为异常(Exception)和错误(Error)。在这种情况下,程序无法继续下去,我们唯一能做的就是跳出当前环境,将问题委托给更高级的负责人。
因此
产生异常时,会发生几件事:首先,创建一个异常对象,该对象与其他Java对象一样存放在内存“堆”中,使用new创建。
然后,停止当前执行路径下的活动(因为已经不能再继续了),抛出异常对象句柄。此时,异常机制会接管一切,开始查找一个合适的地方,用于继续程序的执行。
2.异常分类
所有抛出(throw)的异常都必须是从
Throwable派生而来的。类Throwable有两个直接子类:Error和Exception。由于Throwable是Exception的一个基础类,所以有可能获得一个能够“抛”出的对象(具有Throwable属性),但却并非一个Exception(违例)。因此,在main()中用于Exception的句柄可能丢失自己的目标。
Error类对象由Java虚拟机生成并抛弃,并不会对这类异常进行处理。Error代表编译期和系统错误,如死循环、内存泄露等。
Exception类对象是Java程序处理或抛弃的对象,它有各种不同的子类分别对应不同类型的异常。Exception的一个子类
RuntimeException代表的是运行时由Java虚拟机生成的异常,原因是编程错误;其它的子类都是非运行时的,原因是程序碰到了意外情况,如输入/输出异常IOException。Java编译器要求程序必须捕获或声明所有的非运行时异常,对于运行时异常可以不做处理。
Java中这两种异常中,一类是从java.lang.Exception类衍生出来的,叫做checked exception,另一类是从java.lang.RuntimeException类中衍生出来的,叫做runtime exception。checked exception这种异常要么用try...catch捕获处理,要么用throws语句声明抛出,否则编译不会通过。而对于runtime exception,java编译器是不会检查它的。
3.异常处理
异常处理主要关键字有:try, catch, throw, throws, finally。
其中
try, catch, finally都不能单独使用,可以组成:try...catch...finally, try...catch, try...finally三种结构,而且catch可以多个,finally最多只能有一个。对于多个catch语句,只会匹配其中一种异常类型,而且匹配顺序是自顶下先的。finally语句块无论如何都会执行,不管try语句块中是否出现异常,而且是在return语句之前,不论二者先后位置。throw语句后的语句都不会执行了,当然finally语句还是会执行的,finally语句只有在System.exit()之后不会执行,因为System.exit()是终止当前运行的JVM。
throws关键字用于方法体外部的方法声明部分,用来声明该方法可能会抛出的异常类型。
throw
关键字用于方法内部,用来抛出一个Throwable类型的异常,并且在该方法的头部还必须声明可抛出的异常类型:
public void Fun throws Exception{
...
if (...){
throw new Exception();
}
}
在头部声明的可抛出异常类型和方法体内throw的异常类型要匹配。如果方法体内部使用throw抛出异常,但方法体外部声明没有“throws 异常类型”编译无法通过。此外,该方法的调用者也必须检查处理抛出的异常,如果所有的方法都层次上抛获取的异常,最后会由JVM进行简单的处理,即打印异常消息和堆栈消息。
参考:Think in Java