zoukankan      html  css  js  c++  java
  • [02] 异常链和自定义异常


    1、异常链

    1.1 throw

    我们之前比喻过,说异常的抛出就像棒球中的投球,其中RuntimeException是发生意外后程序自行抛出的,假如我们想要自己抛出异常,就要使用 throw 关键字。
    “野球 イラスト 動物”的图片搜索结果

    显式地抛出异常通常写为:
    throw new xxxException();  

    异常抛出后,有两种处理方式:
    • 立即处理,使用 try catch 捕获并处理
    • 稍后处理,丢给方法调用的上层处理,使用 throws 关键字

    //try-catch 立即处理
    public static void fun() {
        File file = new File("C:/temp.txt");
        if (!file.exists()) {
            try {
                throw new IOException();
            } catch (IOException e) {
                System.out.println("文件不存在");
            }
        }
    }

    //throws 稍后处理
    public static void fun() throws IOException{
        File file = new File("C:/temp.txt");
        if (!file.exists()) {
            throw new IOException();
        }
    }

    使用throw抛出异常时,不要直接使用Exception,或者相互之间有交集的异常,这样不能很好地标记异常的类型,增加了后期维护难度。


    另外,在进行方法覆盖的时候要注意,假如你的某个方法覆盖了父类的某个方法,那么:
    • 不可以增加新的异常,即使这个新异常时父类方法声明中的任何一个异常的子类也不行
    • 不可以抛出 “被覆盖方法抛出异常” 的父类异常

    例如:
    • 父类Animal方法fun()抛出两个异常:IndexOutOfBoundsException、IOException
    • 子类Cat覆盖方法fun()抛出异常最多两个,可以没有,同时子类抛出的异常,不能是父类抛出异常的父类,比如fun()不能抛出Exception(Exception是IndexOutOfBoundsException和IOException的父类)

    可以这样理解:一个修理家电的人,他能够修理冰箱,电脑,洗衣机,电视机。 一个年轻人从他这里学的技术,就只能修理这些家电,或者更少。你不能要求他教出来的徒弟用从他这里学的技术去修理直升飞机。
    “修理家电”的图片搜索结果

    1.2 throws

    如果抛出当前抛出的异常不希望立即处理,则可以在方法声明处使用throws关键字,指出方法引发的异常。可以声明多种异常类型,以逗号分隔开即可。
    public void test throws xxxException1, xxxException2, xxxException3 { ... }

    “野球 イラスト 動物”的图片搜索结果
    使用了throws的方法,被调用时就必须要求对其内的异常进行处理,同样,要么使用try-catch,要么继续使用throws往上抛,这种不断使用throws往上抛出异常直到被处理,就形成了一个所谓抽象的概念 “异常链”。

    我们有时候在捕获一个异常后会抛出一个新的异常信息,并且希望将原始的异常信息也保存起来,这个时候也需要使用异常链。在Throwable及其子类中的构造器中都可以接受一个cause参数,该参数保存了原有的异常信息,通过getCause()就可以获取该原始异常信息。

    public class Test {
        public void f() throws MyException{
             try {
                 FileReader reader = new FileReader("G:\myfile\struts.txt");  
                 Scanner in = new Scanner(reader);  
                 System.out.println(in.next());
            } catch (FileNotFoundException e) {
                //e 保存异常信息
                throw new MyException("文件没有找到--01", e);
            }  
        }
        
    
        public void g() throws MyException{
            try {
                f();
            } catch (MyException e) {
                //e 保存异常信息
                throw new MyException("文件没有找到--02", e);
            }
        }
        
    
        public static void main(String[] args) {
            Test t = new Test();
            try {
                t.g();
            } catch (MyException e) {
                e.printStackTrace();
            }
        }
    
    }

    com.test9.MyException: 文件没有找到--02
        at com.test9.Test.g(Test.java:31)
        at com.test9.Test.main(Test.java:38)
    Caused by: com.test9.MyException: 文件没有找到--01
        at com.test9.Test.f(Test.java:22)
        at com.test9.Test.g(Test.java:28)
        ... 1 more
    Caused by: java.io.FileNotFoundException: G:myfilestruts.txt (系统找不到指定的路径。)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:106)
        at java.io.FileInputStream.<init>(FileInputStream.java:66)
        at java.io.FileReader.<init>(FileReader.java:41)
        at com.test9.Test.f(Test.java:17)
        ... 2 more

    如果在程序中,去掉e,也就是:throw new MyException("文件没有找到--02");  那么异常信息就保存不了,运行结果如下:
    com.test9.MyException: 文件没有找到--02
        at com.test9.Test.g(Test.java:31)
        at com.test9.Test.main(Test.java:38)


    2、自定义异常

    Java已经给我们提供了很多不同种类的异常,但是即使如此,也并不能预见所有的异常类型,特别是我们在业务上出现的错误。所以Java允许我们自定义异常,来表现程序中遇到的一些特殊问题。

    我们自定义的异常类,主要还是用于标记业务逻辑的问题,避免与标准异常混淆。定义也很简单,只需要继承 Exception 即可

    public class MyException extends Exception {
        
        public MyException(String msg){
            super(msg);    
        }    
        
    } 

    自定义异常中往往不写其他的方法,只需要重载使用的构造方法。当然,也可以不写,使用默认的构造方法即可。

    自定义异常往往是通过 throw 进行抛出使用。


    3、参考链接


  • 相关阅读:
    iOS SQLite函数总结
    转-NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象
    NSUserDefaults保存用户名和密码
    iOS 集成银联支付(绕过文档的坑,快速集成)-转
    iOS微信支付
    iOS生成PDF的关键代码-备忘
    python中的urlencode和urldecode
    python中%r和%s的区别
    ubuntu16.04安装wps
    二进制、八进制、十进制、十六进制之间的转换
  • 原文地址:https://www.cnblogs.com/deng-cc/p/7462493.html
Copyright © 2011-2022 走看看