• 11异常处理


    基础知识

    1、异常是一种Exception类型的对象(异常是一种对象

      因为异常是对象,所以你catch住的也是对象,下面程序代码中catch的参数是Exception类型的ex引用变量

    try {
    
    } catch(Exception ex) { //Exception类型的对象可以是任何它的子类的实例
        //尝试恢复
    }

    2、如果你的程序代码会抓住异常,那是谁把它抛出来的?

    //有风险、会抛出异常的代码
    public
    void takeRisk() throws BadException {//必须声明它会抛出BadException if(abandonAllHope) { throw new BadException();//创建Exception对象并抛出 } } //调用该方法的程序代码 public coid crossFingers() { try { anObject.takeRisk(); } catch(BadException ae) { System.out.println("Aaargh"); ex.printStackTrace();//如果无法从异常中恢复,至少也要使用printStackTrace()来列出有用的信息 } }

    举例:

    public class Test {
    
        int age;
    
        public void getAge(int age) throws AgeException{//声明它会抛出AgeException
            this.age = age;
            if(age > 100) {
                throw new AgeException();//创建AgeException对象并抛出
            }
        }
    
        public static void main(String[] args) {
            Test t = new Test();
            t.getAge(200);//调用会抛出异常的方法
        }
    }
    
    class AgeException extends Exception {//自定义异常AgeException继承Exception
        //
    }

     异常是程序运行期间出现的,区别于程序编译期间的代码错误

    3、为什么编译器不管RuntimeException

      大部分RuntimeException都是因为程序逻辑问题,而不是以你所无法预测或防止的方法出现的

    执行期间失败状况,你无法保证文件一直都在,你无法保证服务器不会死机,但是你可以确保程序

    不会运行不合理的逻辑,例如对只有5项元素的数组取第八个元素的值。

    4、try/catch块的控制流程

     5、finally:无论如何都要执行的部分

    /*
    如果try/catch块有return指令,finally还是会执行,
    流程会条到finally然后再回到return指令
    */
    try {
        turnOvenOn();
        x.bake();
        trunOvenOff();
    } catch (BakingException ex) {
        ex.printStackTrace();
        trunOvenOff();
    }

    6、try/catch/finally/throw/throws实例:

    public class Test {
        public static void main(String[] args) {
            String test = "yes";
            try {
                System.out.println("start try");
                doRisky(test);
                System.out.println("end try");
            } catch(ScaryExteption ae) {
                System.out.println("scary exception");
            } finally {
                System.out.println("finally");
            }
            System.out.println("end of main");
        }
    
        static void doRisky(String test) throws ScaryExteption {
            System.out.println("start risky");
            if("yes".equals(test)) {
                throw new ScaryExteption();
            }
            System.out.println("end risky");//不再执行
            return;//不再执行
        }
    }
    
    class ScaryExteption extends Exception {}//ScaryExteption为自定义异常
    String test = "yes"执行结果:

    String test = "no"执行结果:

    7、处理多重异常

      多重方法可以抛出多个异常,但该方法的声明必须要含有全部可能的检查异常(若两个或两个异常的异常有共同的父类时,可以只声明该父类就行)

    public class Laundry {
        public void doLaundry() throws PantsException, LingerieException {
            //可能抛出两个异常的程序代码
        }
    }
    
    public class Foo {
        public void () {
            Laundry laundry = new Laundry();
            try{
                laundry.doLaundry();
            } catch(PantsException pex) {
                //恢复程序代码
            } catch(LingerieException lex) {
                //恢复程序代码
            }
        }
    }

    8、异常也是多态的

      异常是对象,因此异常也能够以多态的方式来引用

     

    9、可以用父类来处理所有的异常并不代表就应该这么做

      把异常处理程序代码写成只有一个catch块以父型的Exception来捕获

    try {
        laundry.doLaundry();
    } catch (Exception ex) {//恢复什么?这个会捕获所有的异常,一次你会搞不清楚哪里出错
        //解决方案......
    }

      有多个catch块时要从小到大,不能把大篮子放在小篮子上面(否则会无法通过编译)

    个人理解:下面例子中:当我们用父类捕获异常时(多个子类捕获效果一致)实际上在第一个异常抛出的时候就catch住了,而后程序就会执行恢复此问题的方法,程序结束。

          我们不能用父类捕获异常是因为程序运行的时候,会根据捕获的不用异常执行不同的恢复该异常的方法,如果我们用父类捕获异常,那么只能写一个

          异常的恢复方法,难以满足一个恢复方法恢复所有类型的异常

    public class Test {
    
        int age;
    
        public void getAge(int age) throws Age1Exception, Age2Exception{
            this.age = age;
            if(age > 100) {
                throw new Age1Exception();
            }
    
            if (age > 200) {//上面抛出异常后,该if语句也不再运行
                throw new Age2Exception();
            }
        }
    
        public static void main(String[] args) {
            Test t = new Test();
            try {
                t.getAge(500);
            }catch (Age1Exception ae) {//只能catch住Age1Exception
                ae.printStackTrace();
            }catch (Age2Exception ae) {//不运行
                ae.printStackTrace();
            }
        }
        /*效果同上面分别catch
        public static void main(String[] args) {
            Test t = new Test();
            try {
                t.getAge(500);
            }catch (Exception ae) {
                ae.printStackTrace();
            }
        }
        */
    }
    
    class Age1Exception extends Exception {}
    class Age2Exception extends Exception {}

    10、不想处理异常时。可以把它duck掉来避开(交给下一个调用的方法来处理

    (ducking只是在踢皮球,早晚还得有人来处理这件事,如果连main()也duck掉异常,程序可编译但是运行报错)

    执行结果:

     

  • 相关阅读:
    是否完全二叉搜索树 (30 分)
    链表去重
    关于堆的判断
    玩转二叉树
    hdu-2795 Billboard(线段树)
    线段树超级大模版
    博弈dp 以I Love this Game! POJ
    kuangbin 最小生成树
    Infinite Maze CodeForces
    Alice’s Stamps HDU
  • 原文地址:https://www.cnblogs.com/wmjlh/p/7297575.html
Copyright © 2020-2023  润新知