Java之异常

      何为异常,根据表面意思就是不正常的称为异常,异常会导致程序中断,或者是出现难以想象的结果。

那么今天就总结一下什么是异常,怎么处理异常,异常处理的作用与意义,还有return 语句与finally块的顺序

一、什么是异常

    java中所有的异常都继承自Throwable类,称为异常的始祖,它有两个儿子,error和Exception 。error是错误的意思,当error出现的时候,那么便出现了不可修复的错误,就好比工厂停电、停水、不可修复的问题.error就是系统级的错误或者是程序不必处理的异常,是java运行环境中的内部错误或者是硬件的问题,对于这种错误程序一般无能为力,只能退出程序重新运行,有可能的话,它会在系统层被捕获,是不可控的;Exception是程序的问题,程序可以进行捕获并处理,可以是可控的或者不可控的,可控的指的是会编译器发现的错误,不可控的是编译器允许通过但是在运行时会抛出异常的错误。

                                                                  Throwable

          error                                                                         Exception

-VirtualMachineError  -ThreadDeath       RuntimeException                                            other     

                        -----ClassCastException            -----IOException

                      ------ArrayIndexOutOfBoundsException     -----SQLException

                      ------NullPointerException

                      ------ArithmeticException

                      

      以上便是部分的继承关系,由于写的比较乱,所以在这里稍微说一下,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中的一个非常重要的机制,防止程序崩溃,在以后的程序中我们要多多使用。

今天总结的是Java的异常处理,如果什么错误或者缺漏还请大神指教,谢谢[笑脸]。

  

                                

原文地址:https://www.cnblogs.com/future-liu1121/p/6539303.html