• 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的异常处理,如果什么错误或者缺漏还请大神指教,谢谢[笑脸]。

      

                                    

  • 相关阅读:
    矩阵快速幂
    快速排序
    用闭包来实现命令模式
    闭包和面向对象设计
    闭包及其作用
    阿里笔试
    如何在节点上添加样式
    getComputedStyle与currentStyle获取样式(style/class)
    今日头条笔试
    牛客网JavaScript编程规范
  • 原文地址:https://www.cnblogs.com/future-liu1121/p/6539303.html
Copyright © 2020-2023  润新知