• 异常处理机制


    1.异常处理

    1.1 概念:

    异常就是程序在运行中出现不正常的情况并终止了程序的运行。

    JAVA中通过异常处理机制解决异常问题,从而保持程序继续运行;因此JAVA是一门比较稳定的语言。

    异常处理机制的关键字:try...catch...finally/try...catch

    1.2 try...catch

    解释:将有可能出现异常的语句放到try中,当出现异常时catch会捕获到

    【1】printStackTrace:打印异常执行的堆栈信息

    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)

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

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

    最后一行:异常出现的位置(类->方法->方法具体的行)

    在控制台中异常堆栈信息输出位置不固定

    【2】getMessage:返回异常的描述信息

     1 package cn.sxt02.exception02;
     2 import java.util.Scanner;
     3 public class Test01 {
     4     public static void main(String[] args) {
     5         Scanner sc = new Scanner(System.in);
     6         System.out.println("请输入第一个数:");
     7 
     8         int num1 = 0;
     9         int num2 = 0;
    10         
    11         try {
    12             num1 = sc.nextInt();
    13 
    14             System.out.println("请输入第二个数:");
    15             num2 = sc.nextInt();
    16 
    17             int r = 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     }
    34 }

    【3】异常类型不匹配

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

    Exception是所有异常直接或间接的父类,因此当出现异常类型不匹配的时候可以这样写catch (Exception e)或者

    catch省略,变成try…finally块;

    1.3 try...catch...finally

    finally块用于进行收尾工作(关闭数据库、关闭文件、释放内存等资源)

    无论出不出现异常finally模块都会执行,当然也有特殊情况那就是添加一句system.exit();正常退出jvm,finally就不会执行

     1 public static void main(String[] args) {
     2         Scanner sc = new Scanner(System.in);
     3         System.out.println("请输入第一个数:");
     4 
     5         int num1 = 0;
     6         int num2 = 0;
     7 
     8         try {
     9             num1 = sc.nextInt();
    10 
    11             System.out.println("请输入第二个数:");
    12             num2 = sc.nextInt();
    13 
    14             int r = 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.4 return

    return 会出现try/catch/finally执行顺序

     1 package cn.sxt02.exception03;
     2 
     3 /**
     4  * 存在return的情况
     5  */
     6 public class Test02 {
     7 
     8     public static int div(int a, int b) {
     9 
    10         try {
    11             int r = a / b;
    12             return r;
    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     public static void main(String[] args) {
    26 
    27         int r = Test02.div(10, 0);
    28         System.out.println("r=" + r);
    29         System.out.println("程序正常结束");
    30     }
    31 }

    解释:先执行try模块然后执行cacth,在执行finally 最后才执行return 0;以上例子为例

    2.异常分类

    从上图可知异常和错误的最终父类都是object,异常分为两类运行时异常(RuntimeException)和检查时异常(CheckException)

    2.1 RuntimeExcption

    运行时异常可处理可不处理

    2.2 CheckException

    检查时运行必须得处理,不然将无法编译

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

    2.3 常见的运行时异常(面试题写出5-8个)

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

    InputMismatchException:输入不匹配异常

    ArrayIndexOutofBoundsException:数组下标越界异常。

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

    IllegalArgumentException:非法参数异常。

    ClassCastException:强制类型转换异常。

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

    2.4 常见的检查时异常:

    ClassNotFoundException:类没有被发现异常。

    SQLException:数据库相关异常

    IOException:IO操作异常

    ParseException:解析错误异常

    FileNotFoundException:文件未发现异常。

    2.5 运行时异常和检查时异常的区别

    运行时异常:包括RuntimeException及其所有子类。不要求程序必须对它们作出处理,比如InputMismatchException、ArithmeticException、NullPointerException等。即使没有使用try-catch或throws进行处理,仍旧可以进行编译和运行。如果运行时发生异常,会输出异常的堆栈信息并中止程序执行。

    Checked异常(非运行时异常):除了运行时异常外的其他异常类都是Checked异常。程序必须捕获或者声明抛出这种异常,否则出现编译错误,无法通过编译。处理方式包括两种:通过try-catch捕获异常,通过throws声明抛出异常从而交给上一级调用方法

    3.异常声明

    3.1 throws关键字

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

     1 public class Test01 {
     2 
     3     public static int div(int a, int b) throws ArithmeticException{
     4         int r = 0;
     5         r = a / b;
     6         return r;
     7     }
     8 
     9     public static void main(String[] args) {
    10         try {
    11             Test01.div(10, 0);
    12         } catch (ArithmeticException e) {
    13             System.out.println("除数不能为0");
    14         }
    15     }
    16 }

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

    如果调用处也不知道如何处理异常,可选择继续声明异常,我们把这个过程称为异常上抛。

     1 public class Test01 {
     2 
     3     public static int div(int a, int b) throws Exception{
     4         int r = 0;
     5         r = a / b;
     6         return r;
     7     }
     8 
     9     public static void 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 }

    3.2 声明异常与重载关系

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

     1 public class Test01 {
     2 
     3     public static int div(int a, int b) throws Exception{
     4         int r = 0;
     5         r = a / b;
     6         return r;
     7     }
     8     
     9     public static int div(int a, int b) {
    10         int r = 0;
    11         r = a / b;
    12         return r;
    13     }
    14 }

    方法重载

    【1】方法名相同
    【2】参数列表不同(个数、类型、顺序)

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

    3.3 声明异常和重写关系

    【1】声明一个和方法重写有关系

     1 public class Father {
     2 
     3     public void showInfo() throws Exception{
     4         
     5     }
     6 }
     7 
     8 public class Son extends Father{
     9     
    10     @Override
    11     public void showInfo(){
    12         
    13     }
    14     
    15 }

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

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

     1 public class Father {
     2 
     3     public void showInfo(){
     4         
     5     }
     6 }
     7 public class Son extends Father{
     8     
     9     @Override
    10     public void showInfo() throws Exception{
    11         
    12     }
    13     
    14 }

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

     1 public class Father {
     2 
     3     public void showInfo() throws Exception{
     4         
     5     }
     6 }
     7 public class Son extends Father{
     8     
     9     @Override
    10     public void showInfo() throws Exception {
    11         
    12     }
    13     
    14 }

    4.手动抛出异常

    4.1  关键字throw

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

     1 package cn.sxt02.exception06;
     2 
     3 public class Student {
     4     private String name;
     5     private String gender;
     6 
     7     public String getName() {
     8         return name;
     9     }
    10 
    11     public void setName(String name) {
    12         this.name = name;
    13     }
    14 
    15     public String getGender() {
    16         return gender;
    17     }
    18 
    19     public void setGender(String gender) throws Exception{
    20         if(gender.equals("男") || gender.equals("女")) {            
    21             this.gender = gender;
    22         }else {
    23             throw new Exception("性别不合法!");
    24         }
    25     }
    26 
    27     public Student(String name, String gender) {
    28         super();
    29         this.name = name;
    30         this.gender = gender;
    31     }
    32 
    33     public Student() {
    34         super();
    35     }
    36     
    37 }
    38 
    39 public class Test01 {
    40     public static void main(String[] args){
    41         Student stu = new Student();
    42         stu.setName("二狗");
    43         try {
    44             stu.setGender("xxx");
    45         } catch (Exception e) {
    46             System.out.println(e.getMessage());
    47         }
    48     }
    49 }

    4.2  自定义异常

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

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

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

     1 public class AgeException extends Exception{
     2 
     3     public AgeException() {
     4         super();
     5     }
     6 
     7     public AgeException(String message) {
     8         super(message);
     9     }
    10     
    11 }
  • 相关阅读:
    define和typedef
    keil5配置stm32库函数开发
    SPI、CAN、I2C
    flash,sram
    关于网络地址
    关于定时器、波特率、TH和TL值的计算
    关于串口工作方式
    ad各层
    AD快捷键
    OAuth2.0 微博登陆网站功能的实现(一)获取用户授权及令牌 Access Token
  • 原文地址:https://www.cnblogs.com/xfbb/p/10776801.html
Copyright © 2020-2023  润新知