何为异常,根据表面意思就是不正常的称为异常,异常会导致程序中断,或者是出现难以想象的结果。
那么今天就总结一下什么是异常,怎么处理异常,异常处理的作用与意义,还有return 语句与finally块的顺序
一、什么是异常
java中所有的异常都继承自Throwable类,称为异常的始祖,它有两个儿子,error和Exception 。error是错误的意思,当error出现的时候,那么便出现了不可修复的错误,就好比工厂停电、停水、不可修复的问题.error就是系统级的错误或者是程序不必处理的异常,是java运行环境中的内部错误或者是硬件的问题,对于这种错误程序一般无能为力,只能退出程序重新运行,有可能的话,它会在系统层被捕获,是不可控的;Exception是程序的问题,程序可以进行捕获并处理,可以是可控的或者不可控的,可控的指的是会编译器发现的错误,不可控的是编译器允许通过但是在运行时会抛出异常的错误。
以上便是部分的继承关系,由于写的比较乱,所以在这里稍微说一下,Throwable 是最高级的类,它有两个子类是error和Exception ,error 主要有两个儿子是虚拟机错误和线程死锁,当这些错误出现时程序便会崩溃,出现不可控的错误;Exception 主要是环境、编码和用户输入错误等,可以控制的,它主要是 RuntimeException 和 其他的异常 ,其中RuntimeException( 运行时异常),称为非检查异常(Unchecked Exception),编译器不会对其进行处理,它主要是: 类型转换异常、数组越界异常、空指针异常、数值计算异常等,这些异常在运行的时候才会被JVM捕获进行处理;而其他的异常被称为检查异常(Checked Exception),在编译的时候编译器会对其进行警告,需要程序员对其手动添加处理块,它主要是IO流异常和SQL语句异常,前者主要是在文件读或者写的时候出现,后者是在执行SQL时出现。当然,也有其他的异常,这里便不一一列举了。
小结:异常就是Java程序抛出的错误,分为可处理和不可处理的,可处理的又分为检查和非检查的,检查的在编译器时便会提示解决,非检查的在运行时才会被抛出需要程序员手动处理。
二、怎么处理异常
为了让程序能按照程序员的想法正常执行,我们必须要对可能出现的异常进行处理,利用try-catch块或者try-catch-finally去解决,其中具体的用法是:
try{
//可能会出现异常的语句
}catch(Exception e){ //捕获的异常
//对异常进行处理
}
try{
//可能会出现的错误
}catch(Exception e) {//抛出的异常
//对异常进行相应的处理
}finally{
//最终会执行的一些操作,比如释放资源,关闭链接等
}
举个例子如下:
try{
while(divider > -1){
divider--;
result=result+100/divider;
}
return result;
}catch (Exception e){
e.printStackTrace();
System.out.println("循环抛出异常了!!!");
return -1;
}
上面的代码可能会出现除数为0的错误,抛出一个ArithmeticException,接着catch便捕获这个异常在其内部对其进行处理,上面的仅仅是对其进行堆栈内的错误信息的打印,并且输出一句话、返回-1,这就是一个简单的异常处理
finally的例子:
try{
while(divider > -1){
divider--;
result=result+100/divider;
}
return result;
}catch (Exception e){
e.printStackTrace();
System.out.println("循环抛出异常了!!!");
return 999;
}finally {
System.out.println("我是finally语句,我执行完了");
System.out.println("我的返回值是:"+result);
}
上面的例子中在try-catch的基础上再执行一下finall中的内容,输出两句话,当然一般的finally中一般是会进行资源的释放或者close链接
现在,我们的重点来了,关于try-catch中含有return 时try-catch-finally的执行顺序的问题,这段代码是我拷的一位大神的,因为具有典型性,所以用来举例再合适不过,大神的链接:http://blog.csdn.net/hguisu/article/details/6155636,
public class TestException {
public TestException() {}
boolean testEx() throws Exception {
boolean ret = true;
try{
ret = testEx1();
}catch(Exception e) {
System.out.println("testEx, catch exception");
ret = false;
throw e;
}finally{
System.out.println("testEx, finally; return value=" + ret);
return ret;
}
}
boolean testEx1() throws Exception {
boolean ret = true;
try{
ret = testEx2();
if(!ret) {
return false ;
}
System.out.println("testEx1, at the end of try");
return ret;
}catch(Exception e) {
System.out.println("testEx1, catch exception");
ret = false;
throw e;
}finally{
System.out.println("testEx1, finally; return value=" + ret);
return ret;
}
}
boolean testEx2() throws Exception {
boolean ret = true;
try{
int b = 12 ;
int c;
for(int i = 2; i >= -2; i--) {
c = b / i;
System.out.println("i=" + i);
}
return true;
}catch(Exception e) {
System.out.println("testEx2, catch exception");
ret = false;
throw e;
}finally{
System.out.println("testEx2, finally; return value=" + ret);
return ret;
}
}
public static void main(String[] args) {
TestException testException1 = new TestException();
try{
testException1.testEx();
}catch(Exception e) {
e.printStackTrace();
}
}
}
上面的代码的返回值是什么呢?
没错,就是上面的结果,接下来我们来讨论讨论为什么会出现这样的结果
首先,在testEx2中输出i=2,i=1. ret的值为true,try中抛出一个异常(这里的return 便不会再被执行),被catch捕获,输出
testEx2, catch exception
, ret=false,并且向调用者抛出一个异常,接着去执行finally语句,输出“
testEx2, finally; return value=false
接着执行return ret;
然后我们来到调用者testEx1中,ret得到testEx2的返回值false,然后去执行if语句,return false,由于没有抛出异常,则直接执行finally语句,输出
testEx1, finally; return value= false",
这里有两个问题:1.在try中为什么没有顺序执行return 后的语句?2.为什么testEx2中抛出的异常没有了???
a.在try中如果有return 语句,当没有异常抛出时,执行到了return ,return 后面的语句便不会再被执行,并且直接跳过catch语句,执行finally(当然如果有的话),然后再接着执行下面的语句
b.在try中如果有return 语句,当有异常抛出的时候,便不会再执行抛出异常语句后面的语句,异常被catch捕获,执行catch中的语句,不会再返回执行try中的return ,而是接着向下执行
c.在catch中如果有return语句,当catch中没有异常抛出的时候,执行了return ,不会再执行catch中return 后面的语句,而是接着执行后面的语句,包括finally语句
d.在catch中如果有return 语句,并且有异常抛出且在return 语句之前,则抛出异常,不会再执行return 语句包括catch 中return 其后的语句,而是去执行finally或者后面的语句
e.当catch中有异常抛出,并且finally中有return 语句,那么catch中的异常会被return 语句吃掉,不会抛出
f.当catch中有异常抛出,finally中没有return 语句,那么catch中的异常会被抛出给它的调用者
finally是无论如何都会被执行的!!!
接着跟前边的一样,执行testEx1的调用者testEx输出"
testEx, finally; return value= false
三、异常处理的作用与意义
处理异常的作用与意义:
a.处理一些小的异常可能会使整个程序避免出现更大的错误,防微杜渐
b.代码组织更清晰了,且更容易实现了,因为把真正的工作和异常分开来处理了
c.给用户一个改错的机会,如果用户不小心输入错误,程序要作出错误提示,交互性比较好
d.可以有一个更可靠的执行流,return 语句可以跳转到调用者一些返回值
f.如果被调用者处理不了可以抛给调用者,让调用者去处理,如果直到main还处理不了,那就抛给JVM去处理
总之,异常处理是Java中的一个非常重要的机制,防止程序崩溃,在以后的程序中我们要多多使用。