• 【Java之路】——异常处理


    异常

    ​ 在java中用类的形式对不正常情况进行了描述和封装对象。描述不正常的情况的类,就称为异常类。以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高阅读性。其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述。不同的问题用不同的类进行具体的描述,比如角标越界,空指针等。问题很多,意味着描述的类也很多,将其共性进行了向上抽取,形成了异常体系,最终问题(不正常情况)就分成了两大类:error和Exception(异常);

    概念

    • 在运行时期发生的不正常情况

    • 异常是一个类,产生异常就是创建异常对象并抛出一个异常对象。

      Java处理异常的方式是中断处理。

    • 异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行

    异常的根类Throwable

    特点

    • Throwable及其所有的子类都具有可抛性
    • 子类的后缀名都是用其父类名作为后缀,阅读性很强

    分类

    Error

    是由jvm抛出的严重性的问题,这种问题发生一般不针对性处理,直接修改程序。

    Exception(异常)

    • 特点

      异常产生后,可以通过代码的方式纠正,使程序继续运行,是必须要处理的。

    • 分类:根据在编译时期还是运行时期去检查异常 分为两种。

      • 编译时期异常:checked异常

        在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)

        • 分类:除了特殊子类RuntimeException体系,Exception和其子类都是。

          • IOException
          • ClassNotFoundException
          • CloneNotSupportException
      • 运行时期异常:runtime异常

        直接编译通过,在运行时期,检查异常 。

        • RuntimeException和其子类

    常用方法

    • public void printStackTrace()

      • 打印异常的详细信息。
      • 包含了异常的类型,异常的原因,还包括异常出现的位置,
    • public String getMessage()

      • 获取发生异常的原因。
      • 提示给用户的时候,就提示错误原因。

    异常的产生过程

    下面以角标越界异常(ArrayIndexOutofBoundsException)为例,代码如下:

    public class ExceptionDemo {
        public static void main(String[] args) {
            int[] arr = { 34, 12, 67 };
            int num = ArrayTools.getElement(arr, 4);
            System.out.println("num=" + num);
            System.out.println("over");
        }
    }
    
    class ArrayTools {
        // 对给定的数组通过给定的角标获取元素。
        public static int getElement(int[] arr, int index) {
            int element = arr[index];
            return element;
        }
    }
    

    图解

    异常发生后,函数就结束,后面的语句就不再访问,在本例中我们自己抛异常,异常信息自定义,代码如下。

    class ArrayTools {
        // 对给定的数组通过给定的角标获取元素。
        public static int getElement(int[] arr, int index) {
            if(arr == null)
                throw new NullPointerException("数组的引用不能为空"); //throw抛出一个异常对象
            if(index >= arr.length)
                throw new ArrayIndexOutOfBoundsException("数组越界了:"+index);
            if(index < 0)
                throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数:"+index);
    
            int element = arr[index];
            return element;
        }
    }
    

    抛出异常

    Java程序的执行过程中如出现异常, 会生成一个异常类对象,该异常对象将被提交给Java运行时系统, 这个过程称为抛出(throw)异常。

    格式:throw new 异常类名(参数)

    例如:

    throw new NullPointerException("要访问的arr数组不存在");
    throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
    

    异常对象的生成:

    自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出

    手动创建:Exception exception = new ClassCastException();创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样

    举例:

    package java_demo_2.exceptiondemo;
    
    /**
     * @ClassName: Demo02_Exception
     * @author: benjamin
     * @version: 1.0
     * @description: TODO
     * @createTime: 2019/07/21/15:47
     */
    
    public class Demo02_Exception {
        public static void main(String[] args) {
    //创建一个数组
            int[] arr = {2, 4, 52, 2};
    //根据索引找对应的元素
            int index = 4;
            int element = getElement(arr, index);
            System.out.println(element);
            System.out.println("over");
        }
    
        /*
        根据 索引找到数组中对应的元素
        */
        public static int getElement(int[] arr, int index) {
            //判断 索引是否越界
            if (index < 0 || index > arr.length - 1) {
            /*
            判断条件如果满足,当执行完throw抛出异常对象后,方法已经无法继续运算。
            这时就会结束当前方法的执行,并将异常告知给调用者。这时就需要通过异常来解决。
            */
                throw new ArrayIndexOutOfBoundsException("哥们,角标越界了~~~");
            }
            int element = arr[index];
            return element;
        }
    }
    

    运行结果:

    那么我们通过throw将异常进行抛出后,也就是将问题返回给调用者后,对用调用者有了两种处理方法,一个是继续将问题声明出去,使用throws声明处理,另一个是捕获处理。

    异常处理体系

    如果异常出现的话,会立刻终止程序,所以我们得处理异常:

    1. 在方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
    2. 在方法中使用try-catch的语句块来处理异常。

    声明异常throws

    概念

    表示当前方法不处理异常,而是提醒该方法的调用者来处理异常。

    格式

    修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }

    注意:在方法声明中用throws语句可以声明抛出异常的列表, throws后面的异常类型可以是方法中产生的异常类型, 也可以是它的父类。

    throw和throws区别

    • throw

      • 抛出异常对象
      • 使用在函数内
      • throw new 异常类名(参数),举例:throw new NullPointerException("要访问的arr数组不存在");
    • throws

      • 抛出异常类
      • 使用在函数上
      • 可以抛多个,用,隔开

    捕获异常try...catch...

    概念

    Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。

    格式

    try{
    	编写可能会出现异常的代码
    }catch(异常类型  e){
    	处理异常的代码
    	//记录日志/打印异常信息/继续抛出异常
    }
    
    • 使用finally代码块

      • try...catch....finally:自身需要处理异常,最终还得关闭资源。
      • 不论在try代码块中是否发生了异常事件, catch语句是否执行, catch语句是否有异常, catch语句中是否有return,finally块中的语句都会被执行
      • 当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行
    • 注意

      多个异常采用一次捕捉多次处理

      格式

      try{
      	编写可能会出现异常的代码
      }catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获.
      	处理异常的代码
      	//记录日志/打印异常信息/继续抛出异常
      }catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获.
      	处理异常的代码
      	//记录日志/打印异常信息/继续抛出异常
      }
      

      注意

      • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

      • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

    自定义异常类

    概念

    对于负数为角标的情况,自己自定义一个用负数角标异常来表示。负数角标这种异常在java中并没有定义过,按照java异常的创建思想,将负数角标进行自定义描述,并封装成对象。这种自定义的问题描述称为自定义异常。

    一般地,用户自定义异常类都是RuntimeException的子类。

    自定义异常类通常需要编写几个重载的构造器。

    自定义异常需要提供serialVersionUID

    自定义的异常通过throw抛出。

    自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。

    步骤

    1. 自定义一个异常类XxxException,继承现有的异常类

      • 自定义编译期异常 :自定义类并继承于java.lang.Exception

      • 自定义运行时期异常:自定义类并继承于java.lang.RuntimeException

    2. 使用到自定义异常的其他类

      • 方法上:throws 异常类名;

      • 方法内:throw new 异常类名(参数);

    代码举例:

    模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。

    1. 定义一个异常类: RegisterException继承与Exceptions

    2. 模拟登录操作,使用数组模拟数据库中存储的数据,并提供当前注册账号是否尊才方法用于判断。

      // 登录异常类
      public class RegisterException extends Exception{
      
          public RegisterException() {
              super();
          }
      
          public RegisterException(String message) {
              super(message);
          }
      }
      
      //自定义一个使用异常的类
      class Demo{
          //模拟数据库中已存在的账号
          private static String[] names = {"admin","tony","benjie"};
      
          public static void main(String[] args) {
              // 从键盘输入一个名字
              Scanner scanner = new Scanner(System.in);
              System.out.println("请输入一个名字:");
              String uname = scanner.next();
              // 调用方法
              try {
                  checkUserName(uname);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          
          public static boolean checkUserName(String uname) throws Exception{
              for(String name: names){
                  if(name.equals(uname)){
                      throw new RegisterException("亲"+uname+"已经被注册了!");
                  }
              }
              return true;
          }
      }
      

    总结:

    异常处理的5个关键字

    try:执行可能产生异常的代码

    catch:捕获异常

    finally:无论是否发生异常,代码总被执行

    throw:抛出异常。异常的生成阶段,手动抛出异常对象。throw new 异常类名(参数),例如:throw new NullPointerException("要访问的数组不存在");

    throws:声明异常。异常的处理方式,声明方法可能要抛出的各种异常类。

  • 相关阅读:
    亚马逊云IoT平台接入开发记录
    pip下载速度慢更换清华源试试
    gitlab回归上一次提交
    uos桌面壁纸存放路径
    python中json中的dump和dumps
    Python中的类中__dict__方法
    C++ | 数组反转的三种方法
    《C++Primer Plus》 | 复合类型
    pwn 中的函数 | 持续更新
    七月安恒DASCTF | 复现
  • 原文地址:https://www.cnblogs.com/benjieqiang/p/11221449.html
Copyright © 2020-2023  润新知