Java的异常处理机制
【摘要】 出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用...)时,JAVA就会用异常对象来描述.
JAVA中用2种方法处理异常:
1.在发生异常的地方直接处理;
2.将异常抛给调用者,让调用者处理.
JAVA异常可分为3种:
(1)检查性异常:java.lang.Exception
(2)运行期异常:java.lan...
出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用...)时,JAVA就会用异常对象来描述.
JAVA中用2种方法处理异常:
1.在发生异常的地方直接处理;
2.将异常抛给调用者,让调用者处理.
JAVA异常可分为3种:
(1)检查性异常:java.lang.Exception
(2)运行期异常:java.lang.RuntimeException
(3)错误:java.lang.Error
顶层是java.lang.Throwable类,检查性异常,运行期异常,错误都是这个类的子孙类.
java.lang.Exception和java.lang.Error继承自java.lang.Throwable,而java.lang.RuntimeException继承自java.lang.Exception.
检查性异常------程序正确,但外在的环境条件不满足引发.例如:用户错误及I/O问题----程序试图打开一个并不存在的远程Socket端口.这不是程序本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误).对商用软件系统,程序开发者
考虑并处理这个问题.JAVA编译器强制要求处理这类异常,如果不捕获这类异常,程序将不能被编译.
运行期异常------这意味着程序存在bug,如数组越界,0被除,入参不满足规范.....这类异常需要更改程序来避免,JAVA编译器强制要求处理这类异常.
错误------一般很少见,也很难通过程序解决.它可能源于程序的bug,但一般更可能源于环境问题,如内存耗尽.错误在程序中无须处理,而有运行环境处理.
下面分析一下java异常的类图:
Java的异常层次:
使用finally块释放资源
finally 最好不要抛出异常,因为在捕获到异常后,jvm会先执行fianlly里面的代码,执行完毕才回到catch里面的代码,这样如果
finally关键字保证无论程序使用任何方式离开try块,finally中的语句都会被执行。在以下三种情况下会进入finally块:
(1) try块中的代码正常执行完毕。
(2) 在try块中抛出异常。
(3) 在try块中执行return、break、continue。
因此,当你需要一个地方来执行在任何情况下都必须执行的代码时,就可以将这些
代码放入finally块中。当你的程序中使用了外界资源,如数据库连接,文件等,必须将释放这些资源的代码写入finally块中。
必须注意的是,在finally块中不能抛出异常。JAVA异常处理机制保证无论在任何情况下必须先执行finally块然后在离开try块,因此在try块中发生异常的时候,JAVA虚拟机在执行catch()的代码后,先转到finally块执行finally块中的代码,finally块执行完毕后,再向外抛出异常。如果在finally块中抛出异常,try块捕捉的异常就不能抛出,因为被finally抛出异常覆盖了,外部捕捉到的异常就是finally块中的异常信息,而try块中发生的真正的异常堆栈信息则丢失了。(在catch里面同样可以抛出异常,但是也会覆盖掉try里面的异常,执行顺序为 try catch finally, 后面的异常会覆盖前面的异常。)
异常不能影响对象的状态(失败原子性,在practical java里面有讲到)
异常产生后不能影响对象的状态,这是异常处理中的一条重要规则。 在一个函数
中发生异常后,对象的状态应该和调用这个函数之前保持一致,以确保对象处于正确的状态中。
如果对象是不可变对象(不可变对象指调用构造函数创建后就不能改变的对象,即
创建后没有任何方法可以改变对象的状态),那么异常发生后对象状态肯定不会改变。如果是可变对象,必须在编程中注意保证异常不会影响对象状态。有三个方法可以达到这个目的:
(1) 将可能产生异常的代码和改变对象状态的代码分开,先执行可能产生异常的代码,如果产生异常,就不执行改变对象状态的代码。
(2) 对不容易分离产生异常代码和改变对象状态代码的方法,定义一个recover方法,在异常产生后调用recover方法修复被改变的类变量,恢复方法调用前的类状态。
(3) 在方法中使用对象的拷贝,这样当异常发生后,被影响的只是拷贝,对象本身不会受到影响。
异常转换的时候,丢失异常信息
,在JDK1.4.1中,Throwable类增加了两个构造方法,public Throwable(Throwable cause)和public Throwable(String message,Throwable cause),在构造函数中传入的原始异常堆栈信息将会在printStackTrace方法中打印出来
一、"异常类"的组织形式
Java系统类中的方法产生的异常都被组织成"异常类"(还有Error类,不在本文讨论范围),此方法和它相关的"异常类"通过throws关键字关联在一起,并且这些类都必须是Exception类的子类。任何一个自己开发的类的方法中如果可能会产生某种异常,也可以将这种异常组织成一个"异常类",但这个"异常类"同样必须是Exception的子类,或孙子类等等。
例1:
/*isLegal于检查数据是否合法,当>0时视为合法,返回合法值,
*否则视为不合法,抛出"异常"。*/
int isLegal(int dt) throws LowZeroException // 这种定义本文中均称为方法与"异常"通
{ // 过throws建立了关联
if(dt>=0){
return data;
}
else
throw new LowZeroException();
}
/*自已写的异常类,继承自Exception*/
class LowZeroException extends Exception
{
public LowZeroException(){
super();
}
}
仔细观察方法isLegal(),它体现出的最值得注意的特色是,它有两种方式的函数出口,一种是通过return语句,返回的是方法本身定义的类型的实例,另一种是通过throw,返回的是"异常类"的对象实例,Java中称之为抛出"异常"。
文章来源: gamwatcher.blog.csdn.net,作者:香菜聊游戏,版权归原作者所有,如需转载,请联系作者。
原文链接:gamwatcher.blog.csdn.net/article/details/6907937
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)