• 异常处理(try...catch...final 和 throw , throws)


    1.传统(弱语言)处理异常方式

    原理:利用判断来控制异常出现

     1 publicclass Test01 {
     2     publicstaticvoid main(String[] args) {
     3         Scanner sc = new Scanner(System.in);
     4         System.out.println("请输入第一个数:");
     5         
     6         intnum1 = 0;
     7         if(sc.hasNextInt()) {            
     8             num1 = sc.nextInt();
     9             
    10             System.out.println("请输入第二个数:");
    11             intnum2 = 0;
    12             if(sc.hasNextInt()) {
    13                 num2 = sc.nextInt();
    14                 
    15                 if(0 == num2) {
    16                     System.out.println("除数不能为0!");
    17                 }else {                    
    18                     intr = num1 / num2;
    19                     System.out.println("num1/num2 = "+r);
    20                 }
    21 
    22             }else {
    23                 System.out.println("第二个数输入不是数字");
    24             }
    25             
    26         }else {
    27             System.out.println("第一个数输入不是数字!");
    28         }
    29     }
    30 }

    这样做的缺点:

    【1】通过判断处理异常影响执行效率。

    【2】判断逻辑和业务逻辑交织在一起,不利于后期维护。

    2.异常

    异常是所有异常类的直接或间接父类。

    异常是指在运行过程中发生了不正常的情况,这是它就会中断程序。

    异常处理机制:指java中异常处理机制为程序提供处理异常的能力,从而使程序不中断的运行。

     3.异常处理

    异常处理的关键字有:try...catch 和 try...catch...finally  

    1)try...catch

    解释:try— 把有可能产生异常的代码放到try代码块中,catch—负责捕获异常并匹配异常再处理异常。

    【1】正常执行,没有遇到异常

    【2】出现异常,异常处理,正常结束。(红字是处理异常步骤)

    异常常见方法:

    prinStackTrace:打印异常的执行堆栈信息(在控制台中异常堆栈信息输出位置不固定)

    1 java.util.InputMismatchException
    2     at java.util.Scanner.throwFor(Scanner.java:864)
    3     at java.util.Scanner.next(Scanner.java:1485)
    4     at java.util.Scanner.nextInt(Scanner.java:2117)
    5     at java.util.Scanner.nextInt(Scanner.java:2076)
    6     at cn.sxt02.exception02.Test01.main(Test01.java:14)

    一般,异常的堆栈信息很多,开发者只需要看懂

     ——第一行:异常简单的信息(异常类型,异常描述等)

    ——最后一行:异常出现的位置(如上的Test01.java:14)

    getMessage:返回异常的描述信息

     1 packagecn.sxt02.exception02;
     2 importjava.util.Scanner;
     3 publicclass Test01 {
     4     publicstaticvoid main(String[] args) {
     5         Scanner sc = new Scanner(System.in);
     6         System.out.println("请输入第一个数:");
     7 
     8         intnum1 = 0;
     9         intnum2 = 0;
    10         
    11         try {
    12             num1 = sc.nextInt();
    13 
    14             System.out.println("请输入第二个数:");
    15             num2 = sc.nextInt();
    16 
    17             intr = num1 / num2;
    18             System.out.println("num1/num2 = " + r);
    19         }catch (Exception e) {
    20             System.out.println("程序出现异常");
    21             // 打印异常的信息
    22             // System.out.println(e.toString());
    23             
    24             
    25             // 打印异常堆栈信息
    26             e.printStackTrace();
    27             
    28             // 返回异常的描述信息,如果没有信息,返回null(InputMismatchException没有描述信息)
    29             System.out.println(e.getMessage());
    30         }
    31         
    32         System.out.println("程序正常结束");
    33     }

    【3】异常类型不匹配

    【4】多重catch

     1 publicclass Test03 {
     2     publicstaticvoid main(String[] args) {
     3         Scanner sc = new Scanner(System.in);
     4         System.out.println("请输入第一个数:");
     5     
     6         intnum1 = 0;
     7         intnum2 = 0;
     8         
     9         try {
    10             num1 = sc.nextInt();
    11 
    12             System.out.println("请输入第二个数:");
    13             num2 = sc.nextInt();
    14 
    15             intr = num1 / num2;
    16             System.out.println("num1/num2 = " + r);
    17         }catch (ArithmeticExceptione) {
    18             System.out.println("数学计算异常:"+e.getMessage());
    19         }catch(InputMismatchExceptione) {
    20             System.out.println("输入不匹配异常:"+e.getMessage());
    21         }catch (Exception e) {
    22             System.out.println("发送异常:"+e.getMessage());
    23         }
    24         
    25         System.out.println("程序正常结束");
    26     }
    27 }

    2)try...catch...finally  

     解读:把有可能产生异常的代码放到try的代码块中,catch捕捉异常并匹配异常再处理异常,finally块用于收尾工作

    (如关闭数据库,关闭文件,释放内存等资源)

    注:finally :无论是否发生异常,finally都将执行,常用于收尾工作

     1 publicstaticvoid main(String[] args) {
     2         Scanner sc = new Scanner(System.in);
     3         System.out.println("请输入第一个数:");
     4 
     5         intnum1 = 0;
     6         intnum2 = 0;
     7 
     8         try {
     9             num1 = sc.nextInt();
    10 
    11             System.out.println("请输入第二个数:");
    12             num2 = sc.nextInt();
    13 
    14             intr = num1 / num2;
    15             System.out.println("num1/num2 = " + r);
    16         } catch (Exception e) {
    17             System.out.println("程序出现异常");
    18         } finally {
    19             System.out.println("不管是否出现异常,finally都执行");
    20         }
    21 
    22         System.out.println("程序正常结束");
    23     }

    特殊情况:

    【1】finally不执行的情况

    System.exit(0)正常退出jvm,程序结束,不会执行finally

    【2】catch可以省略,变成try...finally形式

    4.return

    当return存在于try...catch...finally时的执行顺序(return始终在最后)

     1 packagecn.sxt02.exception03;
     2 
     3 /**
     4  * 存在return的情况
     5  */
     6 publicclass Test02 {
     7 
     8     publicstaticintdiv(inta, intb) {
     9 
    10         try {
    11             intr = a / b;
    12             returnr;
    13 
    14         } catch (Exception e) {
    15             System.out.println("出现异常");
    16 
    17             return 0;
    18 
    19         } finally {
    20             System.out.println("我是finally");
    21         }
    22 
    23     }
    24 
    25     publicstaticvoid main(String[] args) {
    26 
    27         intr = Test02.div(10, 0);
    28         System.out.println("r=" + r);
    29         System.out.println("程序正常结束");
    30     }
    31 }

    5.异常的分类

    Throwable类是 Java 语言中所有错误(Error)或异常(Exception)的父类,只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。

    Error 类表示错误类。仅靠程序本身无法恢复的严重错误。如jvm内存耗尽、jvm崩溃等。

    Exception类表示异常类,可以通过java 异常处理机制处理。

    Exception根据是否处理分为两种情况。

    RuntimeException:运行时异常。不要求程序必须做出处理。是所有运行时异常的父类。

    CheckedException:检查时异常。要求程序必须处理,不处理编译不通过。

     1 publicclass Test01 {
     2     publicstaticvoid main(String[] args) {
     3         // 运行时异常
     4         Scanner sc = new Scanner(System.in);
     5         // runtime exception
     6         intr = sc.nextInt();
     7         System.out.println("r = "+ r);
     8         
     9         // 检查时异常
    10         SimpleDateFormatdf = newSimpleDateFormat();
    11         try {
    12             Date date = df.parse("2019");
    13         } catch (ParseExceptione) {
    14             e.printStackTrace();
    15         }
    16     }
    17 }

    常见的运行时异常

    ArithmeticException:数学计算异常。如除数为0

    InputMismatchException:输入不匹配异常。

    ArrayIndexOutofBoundsException:数组下标越界异常。

    NullPointException:空指针异常,对象没有初始化就使用时,jvm就会抛出该异常。

    IllegalArgumentException:非法参数异常。

    ClassCastException:强制类型转化异常。

    NumberFormatException:数字格式化异常。如把“abc”格式化为数字。

    常见的检查时异常:

    ClassNotFoundException:类没有被发现异常。

    SQLException:数据库相关异常
    IOException:IO操作异常
    ParseException:解析错误异常
    FileNotFoundException:文件未发现异常。
    运行时异常和检查时异常的区别:

      运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们作出处理,比如InputMismatchException、                 ArithmeticException、NullPointerException等。即使没有使用try-catch或throws进行处理,仍旧可以进行

            编译和运行。如果运行时发生异常,会输出异常的堆栈信息并中止程序执行。

      检查时异常:Checked异常(非运行时异常):除了运行时异常外的其他异常类都是Checked异常。程序必须捕获或者

            声明抛出这种异常,否则出现编译错误,无法通过编译。处理方式包括两种:通过try-catch捕获异常,

            通过throws声明抛出异常从而交给上一级调用方法处理

    6.声明异常

    1)throws关键字

    解读:当一个方法可能存在异常,而此时自身又无法更好的处理,可以交给外界处理。此时用throws声明并抛出异常。

     1 publicclass Test01 {
     2 
     3     publicstaticintdiv(inta, intb) throws ArithmeticException{
     4         intr = 0;
     5         r = a / b;
     6         returnr;
     7     }
     8 
     9     publicstaticvoid main(String[] args) {
    10         try {
    11             Test01.div(10, 0);
    12         } catch (ArithmeticExceptione) {
    13             System.out.println("除数不能为0");
    14         }
    15     }
    16 }

      注:开发者可以根据需求声明检查时异常 (Exception或者非运行时异常及其子类)  和运行时异常(RuntimeException或其子类)

     如果抛出异常后,调用处不知道如何处理异常,可以选择继续声明异常(抛出异常),这个过程叫做异常上抛。

     1 publicclass Test01 {
     2 
     3     publicstaticintdiv(inta, intb) throws Exception{
     4         intr = 0;
     5         r = a / b;
     6         returnr;
     7     }
     8 
     9     publicstaticvoid main(String[] args) throws Exception{
    10         
    11         //【1】调用处知道如何处理!
    12         /*
    13         try {
    14             Test01.div(10, 0);
    15         } catch (Exception e) {
    16             e.printStackTrace();
    17         }
    18         */
    19         
    20         // 【2】调用处也不知道如何处理
    21         Test01.div(10, 0);
    22         
    23     }
    24 }

    2)声明异常和重载的关系

    声明异常和重载没有任何关系

     1 publicclass Test01 {
     2 
     3     publicstaticintdiv(inta, intb) throws Exception{
     4         intr = 0;
     5         r = a / b;
     6         returnr;
     7     }
     8     
     9     publicstaticintdiv(inta, intb) {
    10         intr = 0;
    11         r = a / b;
    12         returnr;
    13     }
    14 }

    注:方法重载:

    【1】方法名相同

    【2】参数列表不同(个数,类型,不同类型的顺序不同)

    【3】和返回值,修饰符,声明异常无关

     3)声明异常和重写的关系

    声明异常和方法重写有关系,关系如下

    [1]父类方法声明了异常(检测时或运行时),子类可以不声明任何异常。

    publicclass Father {
    
        publicvoidshowInfo() throws Exception{
            
        }
    }
    publicclass Son extendsFather{
        
        @Override
        publicvoidshowInfo(){
            
        }
        
    }

    理解:父类方法抛出异常,子类在重写过程中把该异常处理掉了,所以子类方法不用声明异常。

    [2] 父类方法声明没有声明任何异常(检测时或运行时),子类也不声明异常或者声明运行时异常。

    publicclass Father {
    
        publicvoidshowInfo(){
            
        }
    }
    publicclass Son extendsFather{
        
        @Override
        publicvoidshowInfo() throws Exception{
            
        }
        
    }

    [3]父类声明了异常(检测时或运行时),子类声明完全一样的异常。

    publicclass Father {
    
        publicvoidshowInfo() throwsException{
            
        }
    }
    publicclass Son extendsFather{
        
        @Override
        publicvoidshowInfo() throwsException {
            
        }
        
    }

    7.手动抛出异常

    1)throw

    除了系统自动抛出异常外,有些问题需要开发者手动抛出异常。使用关键字throw

     1 packagecn.sxt02.exception06;
     2 
     3 publicclass Student {
     4     private String name;
     5     private String gender;
     6 
     7     public String getName() {
     8         returnname;
     9     }
    10 
    11     publicvoidsetName(String name) {
    12         this.name = name;
    13     }
    14 
    15     public String getGender() {
    16         returngender;
    17     }
    18 
    19     publicvoidsetGender(String gender) throws Exception{
    20         if(gender.equals("男") || gender.equals("女")) {            
    21             this.gender = gender;
    22         }else {
    23             thrownew Exception("性别不合法!");
    24         }
    25     }
    26 
    27     publicStudent(String name, String gender) {
    28         super();
    29         this.name = name;
    30         this.gender = gender;
    31     }
    32 
    33     publicStudent() {
    34         super();
    35     }
    36     
    37 }
     1 publicclass Test01 {
     2     publicstaticvoid main(String[] args){
     3         Student stu = newStudent();
     4         stu.setName("二狗");
     5         try {
     6             stu.setGender("xxx");
     7         } catch (Exception e) {
     8             System.out.println(e.getMessage());
     9         }
    10     }
    11 }

    2)自定义异常

    理解:如果开发者需要手动抛出的异常在系统不存在,可以自定义异常。

    注意:如果要自定义异常,首先要确定异常类型,如果异常是运行时异常,必须继承RuntimeException或其子类;如果异常是检查时异常,必须继承Exception或其子类。

         ——异常的命名方式,参考系统命名方式,以Exception结尾。

    publicclassAgeExceptionextendsException{
    
        publicAgeException() {
            super();
        }
    
        publicAgeException(String message) {
            super(message);
        }
        
    }
  • 相关阅读:
    在Visual Studio中使用层关系图描述系统架构、技术栈
    在Visual Studio中使用活动图描述业务流程
    在Visual Studio中使用类图描述领域模型
    在Visual Studio中使用用例图描述参与者与用例的关系
    在Visual Studio中使用用例图描述系统与参与者间的关系
    并行编程中的取消任务、共享状态,等等
    等待所有或任意异步任务完成,以及异步任务完成时的处理方案
    使用IProgress实现异步编程的进程通知
    Task.FromResult应用场景举例
    Task.Delay方法的2个应用实例,单元测试等待,限时限次下载远程资源
  • 原文地址:https://www.cnblogs.com/qq2267711589/p/10776695.html
Copyright © 2020-2023  润新知