Java中的异常处理机制概述
在Java中,异常处理机制是非常重要的一个机制。
所谓异常,即Java从面向对象的思想出发,对实际开发中可能出现的问题的描述,将问题看做一个对象,并对问题进行对象的封装。
在Java的异常体系中,存在一个所有异常的超类:Throwable。该类是所有异常的跟类。无论是Error还是Exception,亦或是自定义类型的异常类别,都直接或间接的继承自Throwable。
异常体系如下:
Throwable
|-----Error(错误)
... ...
|-----Exception(异常)
... ...
在学习过程中,主要学习的是Exception异常类别,在Exception中,主要掌握的是RuntiimeException(运行时异常)
异常体系的特点:异常体系中所有的类以及建立的对象都具备可抛性。即也就是说可以被throw(关键字)和throws(关键字),需要注意的是,有且仅有异常体系具备可抛这个特点,并且是所有的。
关于关键字throw和throws的用法及区别:
1、throw定义在函数内,后面跟着的是一个具体的异常对象,如: throw new AException();
2、throws定义函数声明上,后面跟的是抛出的异常名称,可以跟多个异常,多个异常之间用逗号隔开。原则上无先后之分。例如 : public void show() throws AException, BException{...}
具体说明:当函数内有thorw关键字抛出异常对象时,同时并未对异常进行try..catch处理,则根据规则必须要在该函数的定义声明上进行声明,否则编译器会编译失败。
但是,有且仅有一类情况下除外,RuntimeException类及其子类异常除外。也就说,如果一个函数内部如果抛出的异常对象时RuntimeException异常或者是其子类,则该函数的声明上可以不进行声明。在实际使用事,需要特别注意该种情况。
关于异常的处理方式问题
对于异常的处理,其实说来比较灵活,若一个函数声明了异常,则根据规则调用者需要在调用改方法时对异常进行处理,处理方式有两种选择:调用者继续throws,即继续抛出异常,将异常交给其他人处理;第二种处理方式就是调用者对该异常比较熟悉,知道具体的处理方法或者改异常的解决办法,所以可以用try。。catch进行就地处理,也就是当代码出现问题时,立即捕获错误,然后根据自己的意图进行处理。
异常往往分为两种:
1、编译检测的异常,该异常是在对java文件进行编译时进行检测,如果检测到有异常没有处理(没有throws也没有try),则编译不会被通过,即编译失败。
2、运行时异常(RuntimeException):该类别的异常在编译时并不进行检测,符合语法规则。对于该类的异常,并不建议处理,正确的做法应该是让程序停止。原因时,该类的异常说明语法结构并没有错误,发生错误的原因是调用者调用时出现了错误的传值或者其他人为的错误,此时的异常的解决办法应该是修改程序,修正代码,重新运行,而不是隐藏该错误,埋藏隐患。
异常的处理格式(三段式及其组合):
try
{
//需要被检测的代码
}
catch(Exception e)
{
//具体处理异常的代码
}
finally
{
//一定会执行的代码
}
以上是完整的“三段式”异常处理的具体代码格式。实际的过程中,具体的处理方式书写格式可能会有所不一样,具体的“三段式”的变体格式及其组合格式如下两种:
--------
第一种:
try
{
//需要被检测的代码
}
catch(Exception e)
{
//处理异常的具体代码
}
--------
第二种变体:
try
{
//需要被检测的代码
}
finally
{
//一定会被执行的代码
}
--------
特别注意:
1、finally中定义的通常是关闭资源的代码,因为资源必须要释放。例如:操作数据库的连接
2、finally中的代码通常一定会被执行,只有一种情况下除外,即finally出现在System.ext(0);后,这种情况下finally中的代码不会被执行。原因是因为System.exit(0);代表着JVM系统已经退出,也就不会执行了。
关于自定义异常的说明
概念:自定义异常就是按照Java的面向对象的思想,将程序中出现的特有的问题原来的异常体系没有定义过的问题进行封装,此之为自定义异常类,命名往往是特有问题的名字+Exception,如:NoValueException。
自定义类需要继承Exception或者RuntimeException
原因:1、满足异常体系中所有类都可抛的共性特点 2、让该类具备操作异常的共性方法,比如getMessage()。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能,如下解释:
class MyException extends Exception
{
MyException(String message)
{
super(message);
}
}
在程序中使用异常的好处和优点: 1、将问题进行封装,便于理解,查看。 2、将正常的逻辑代码与问题处理代码相分离,方便代码的阅览。
异常的处理原则:
1、两种处理方式:try 或者 throws
2、调用到抛出异常的功能时,抛出几个异常,就处理几个异常(不要多处理,也不要少处理),即通常讲的多异常的情况,代码的体现形式就是一个try对应多个catch的情况。
3、多个catch楚翔的情况时,子类的异常方上面,父类异常方下面。原因:使描述问题更加具体。
4、catch代码块内需要定义针对性的处理方式,而不要简单的定义printStackTrace(),或者仅仅是输出语句。另外,不要啥代码都不写,这样回隐藏问题,埋藏隐患。
5、当捕获到异常情况,本功能处理不了的情况时,可以选择继续抛出。如下:
: try
{
throw new AException();
}
catch(AExcetpion e)
{
throw e;
}
如果该异常处理不了,但并属于该功能出现的异常。可以将异常进行转换后,再抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。当调用者知道,并处理时,也可以可以将捕获的异常处理后,转换成新的异常进行抛出。具体情况不在示例。
最后,说一下异常的注意事项:在子父类覆盖时: 1、子类抛出的异常必须是父类异常的子类或者子集。 2、如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try, 不能抛。