抛出了无数的Exception,但是Exception到底是啥?解开Exception的神秘面纱...
时间:2015-01-20 13:46:16
收藏:0
阅读:317
java异常
什么是异常呢?
定义:当一个程序在运行过程中,出现了一些非正常执行流程的指令,那么就会产生一个事件对象,这个事件对象在java就简称为异常(Exception)。An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program‘s instructions.
异常Handler:
当一个异常出现了,那么jvm就会去寻找一个Handler来处理这个异常。下面树jvm调用过程以及Handler的调用过程,从图中可以看出,Handler过程是反序的。
异常的分类:
异常主要分为三类:Error,代表这个异常非常致命,不需要被异常Handler捕获。
Checked Exception:受检异常,代表异常属于符合用户预期的异常,通常情况下,用户会采取相应的措施,尝试从异常中恢复,需要被异常Handler捕获。
Runtime Exception:运行时异常,通常是一个bug,一般用于表示该异常是用户没有预料到的,不需要被异常Handler捕获。
语法结构:
try语法结构:try {
code
}
catch and finally blocks . . .
catch语法结构:
try {
} catch (ExceptionType name) {
} catch (ExceptionType name) {
}
finally语法结构:
try{
}catch(ExceptionType name){
}finally {
}
直接在方法中抛出并且捕获异常的结构:
public void method1() throws ExceptionType{
}
直接在方法中抛出异常
public void method1(){
if(index < 0){
throw new EmptyStackException();
}
}
异常的作用:
先看一个方法,使用的是伪代码...
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
1打开文件
2查看文件大小
3开辟内存空间
4读取文件内容到内存中
5关闭文件
但是如果这个方法出现如下问题
1文件不可打开
2文件大小不可预知
3内存空间不够了
4如果读取文件失败了
5关闭文件失败了
如果不适用异常来处理这些异常,那么代码会是怎样子呢?
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
每次客户端调用这个方法,都需要判断返回的状态码,从而来决定下一步来做什么...比如:int status = readFile();
switch(status){
case -1: do something...
case -2: do someting...
}这种代码是会让你发疯的,特别是一段时间之后,你再回来看这些代码,你会发现可读性特别差,如果在readFile()中再添加一些新的状态码,那么客户端的代码需要跟着一起
改变,这会给维护带来毁灭性的的工作,并且很容易引入新的bug。
下面是使用异常之后的代码:
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}通过异常,我们可以让代码的可读性更加完整,并且如果新增加异常,也不会改动客户端的代码。
我们再来看看另外一个列子
method1 {
call method2;
}
method2 {
call method3;
}
method3 {
call readFile;
}这是一个方法调用栈,方法method1() call method2() call method()3 call readFile()
如果没用异常处理机制,那么每个方法都会被强制进行错误诊断,那可是相当麻烦的,如下代码:
method1 {
errorCodeType error;
error = call method2;
if (error)
doErrorProcessing;
else
proceed;
}
errorCodeType method2 {
errorCodeType error;
error = call method3;
if (error)
return error;
else
proceed;
}
errorCodeType method3 {
errorCodeType error;
error = call readFile;
if (error)
return error;
else
proceed;
}好吧,看完之后,你会被很多无关代码弄得心烦意乱了,各种乱...
下面我们使用异常来处理:
method1 {
try {
call method2;
} catch (exception e) {
doErrorProcessing;
}
}
method2 throws exception {
call method3;
}
method3 throws exception {
call readFile;
}我们仅仅在只关心的方法中处理异常...瞬间世界美好了。
另外,异常可以帮助我们将一些错误进行分类处理。比如在java.io中,需要各种各种的IO错误,比如打开文件失败,访问文件失败,关闭输出流失败等,我们都可以将这些异常归结为IOException,从更加高的层次去看待问题。
自定义异常:
通常情况下,如果你在开发一个工具包,出现了异常,那么用户可以直接自定义异常。异常的自定义非常简单,通常类名就表示错误类别。如:IllegalArgumentException,IOException,NegativeIndexException,FileNotFoundException等...但是有一点需要注意的是,选择继承的异常类很重要。如果错误是不可预知的,属于bug的,可以继承RuntionException,要么继承Exception吧。
总结:异常给了程序更加高的灵活性,并且让代码更加通熟易懂。所以正确使用异常,是非常重要的。在捕获异常时,应该是做到具体的异常类型,很多人懒惰,就直接在每个方法中throws Exception...可以这会给调试bug带来极大的困难。比如说异常是在一个10个方法堆栈中抛出的,那么异常链就会非常的大,想要定位到错误的所在地是困难的。同样,也不能随意的捕获异常甚至是将异常丢掉了,如下代码try{}catch(Exception){ignore...}。程序明明出现了错误,但是控制台啥也没有输出,这绝对是一个大坑。所以捕获异常的情况一般是:能处理异常,那么就可以捕获异常,如果不行,那么就抛出异常,丢给调用者来决定异常的处理情况。
原文:http://blog.csdn.net/u010469003/article/details/42916253
评论(0)