Java异常处理机制
开发工具与关键技术:myeclipse
撰写时间:2019年08月18日
一、异常简介:
在程序中,错误可能产生于程序员没有预料到的各种情况,或者超出程序员可控范围的环境,例如用户的坏数据、试图打开一个不存在的文件等。为了能够及时有效地处理程序中的运行错误,java专门引入了异常类
Java中的异常(Exception)又称为例外,是一个在程序执行期间发生的事件,它中断正在执行的程序的正常指令流。为了能够及时有效地处理程序中的运行错误,必须使用异常类
二、异常产生的原因及使用原则:
在java中的一个异常的产生,主要有如下三种原因:
1.java内部错误发生异常,java虚拟机产生的异常
2.编写的程序代码中的错误所产生的异常,例如空指针异常、数组越界异常等等。这种异常称为未检查的异常,一般需要在某些类中几种处理这些异常
3.通过throw语句手动生成的异常,这种异常称为检查的异常,一般用来告知该方法的调用者一些必要的信息
Java通过面向对象的方法来处理异常。在一个方法的运行过程中,如果发生了异常,则这个方法会产生代表该异常的一个对象,并把它交给运行时的系统,运行时系统寻找相应的代码来处理这一异常
我们把生成异常对象,并把它提交给运行时系统的过程称为抛出(throw)异常。运行时系统在方法的调用栈中查找,直到找到能够处理该类型异常的对象,这一个过程称为捕获(catch)异常
Java异常强制用户考虑程序的强健性和安全性。异常处理不应用来控制程序的正常流程,其主要作用是捕获程序在运行时发生的异常并进行相应处理。编写代码处理某个方法可能出现的异常,可遵循如下三个原则:
1.在当前方法声明中使用try catch 语句捕获异常
2.一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类
3.如果父类抛出多个异常,则覆盖方法必须抛出那些异常的一个子集,而不能抛出新异常
三、异常类型
在java中所有异常都是内置类java.lang.Throwable类的子类,即Throwable位于异常类层次结构的顶层。Throwable类下有两个异常分支exception和error
Throwable是所有异常和错误的超类,error和exception两个子类分别表示错误和异。其中异常类exception又分为运行时异常和非运行时异常,这两种异常有很大的区别,也成为不检查异常(Unchecked Exception)和检查异常(Checked Exception)
1.exception类用于用户程序可能出现的异常情况,它也是用来创建自定义异常类型类的类
2.Error定义了在通常环境下不希望被程序捕获的异常。Error类型的异常用于java运行时由系统显示与运行时系统本身有关的错误。堆栈溢出是这种错误的一例
运行时异常都是RuntimeException 类及其子类异常,如NullPointerException、IndexOutOfBoundsException 等,这些异常是不检查异常,程序中可以选择捕获处理,也乐意不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生
非运行时异常是指RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、ClassNotFoundException等以及用户自定义的Exception异常,一般情况下不自定义检查异常
Java中常见的异常类型
异常类型 | 说明 |
---|---|
Exception | 异常层次结构的跟类 |
RuntimeException | 运行时异常,多数java.lang异常的根类 |
ArithmeticException | 算术错误异常,如以零做除数 |
ArraylndexOutOfBoundException | 数组大小小于或大于实际的数组大小 |
NullPointerException | 尝试访问null对象成员,空指针异常 |
ClassNotFoundException | 不能加载所需的类 |
NumberF ormatException | 数字转化格式异常,比如字符串到float型数字的转换无效 |
IOException | IO异常的根类 |
FileNotFoundException | 找不到文件 |
EOFException | 文件结束 |
InterruptedException | 线程中断 |
IllegalArgumentException | 方法接收到非法参数 |
ClassCastException | 类型转换异常 |
SQLException | 操作数据库异常 |
在java应用程序中,有两种异常处理机制:抛出异常、捕获异常
四、声明异常抛出异常:
当一个方法出现错误引发异常时,方法创建异常对象交付运行时系统,异常对象中包含了异常类型和异常出现时程序的状态等异常信息。运行时系统负责寻找处置异常的代码并执行
可以通过throws关键字在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象。
Throws关键字和throw关键字在使用上的几点区别:
1.throws用来声明一个方法可能抛出的所有异常信息,throw则是抛出的一个具体的异常类型
2.通常在一个方法(类)的声明处通过throws声明方法(类)可能抛出的异常信息,而在方法(类)内部通过throw声明一个具体的异常信息
3.Throws通常不用显示捕获异常,可由系统自动将所有捕获的异常信抛给上级方法;throw则需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出
throws声明异常
当一个方法产生一个与它不处理的异常时,那么就需要在该方法的头部声明这个异常,以便将该异常传递到犯法的 外部进行处理。可以使用throws关键字在方法的头部声明一个异常
throw抛出异常
Throw语句用来直接抛出一个异常,后接一个可抛出的异常类对象。当throw语句执行时,它后面的语句将不执行,此时程序转向调用者程序,寻找与之相匹配的catch语句,执行相应的异常处理程序。如果没有找到相匹配的catch语句,则再转向上一层的调用程序。这样逐层向上,直到最外层的异常处理程序终止程序并打印调用栈情况
捕获异常
在方法抛出异常后,运行时系统将转换为寻找合适的异常处理器。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次会查调用栈中的方法,直至找到合适的异常处理器的方法并执行。当运行时系统遍历调用方法时,运行时系统终止,同时意味着java程序的终止
通常使用try、catch、finally来捕获异常:
try
{
逻辑代码块
}catch(ExceptionType e)
{
异常处理代码块
}finally
{
清理代码块
}
try块:用于捕获异常。其后可接零个过多个catch块,如果没有catch块,则必须跟个finally块
catch块:用于处理try捕获到的异常
finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try或catch块中遇到return语句时,finally语句块将在方法返回之前被执行
在一下四种特殊情况下,finally块将不会被执行:
1.在finally语句块中发生了异常
2.在前面的代码中用了System.exit(退出程序)
3.程序所在的线程死亡
4.关闭CPU
try、catch、finally语句块的执行顺序:
1.当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句
2.当try捕获大奥异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里还是会被执行,但finally语句块的语句不会被执行
3.当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序爱执行的,但执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,二try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句。