十、异常

异常

程序运行过程中出现的问题在Java中被称为异常,异常本身也是一个Java类,封装着异常信息;我们可以通过异常信息来快速定位问题所在;我们也可以针对性的定制异常

异常体系

Java程序运行过程中所发生的异常事件可分为两类:
image.png

  • Error:表示严重错误,一般是JVM系统内部错误、资源耗尽等严重情况,无法通过代码来处理;
  • Exception:表示异常,一般是由于编程不当导致的问题,可以通过Java代码来处理,使得程序依旧正常运行;

异常的分类

异常的分类是根据是在编译器检查异常还是在运行时检查异常;

  • 编译时期异常:在编译时期就会检查该异常,如果没有处理异常,则编译失败;
  • 运行时期异常:在运行时才出发异常,编译时不检测异常; 对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。

在Java中如果一个类直接继承与Exception,那么这个异常将是编译时异常;如果继承与RuntimeException,那么这个类及它的子类都是运行时异常 。即使RuntimeException也继承与Exception;
image.png

异常处理机制

Java程序的执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统(JVM),当JVM接收到异常,程序会崩溃,这个过程称为抛出(throw)异常。如果一个方法内抛出异常,该异常会被抛到调用方法中。如果异常没有在调用方法中处理,它继续被抛给这个调用方法的调用者。这个过程将一直继续下去,直到异常被处理。这一过程称为捕获(catch)异常。如果一个异常回到main()方法,并且main()也不处理就会抛给JVM,则程序运行终止。

方式一:try-catch-finally(捕获)

  • try
    • 捕获异常的第一步是用try{…}语句块选定捕获异常的范围,将可能出现异常的代码放在try语句块中。
    • 在try结构中声明的变量,再出了try结构以后,就不能再被调用
  • catch
    • 在catch语句块中是对异常对象进行处理的代码。每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
    • 捕获异常的有关信息:与其它对象一样,可以访问一个异常对象的成员变量或调用它的方法。
      • getMessage() 获取异常信息,返回字符串
      • printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
    • 多个catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
    • 多个catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错
  • finally
    • 捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口
    • 不论在try代码块中是否发生了异常事件,catch语句是否执行,catch语句是否有异常,catch语句中是否有return,finally块中的语句都会被执行。因此如果finally有return语句,则方法调用者接收的永远是finally中的结果。我们在开发过程中应该避免该情况;
    • finally语句和catch语句是任选的

image.png
流程
使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(在没有写finally的情况)。继续执行其后的代码。

方式二:throws (抛)

  • 声明抛出异常 是Java中处理异常的第二种方式
    • 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
  • 在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
  • 手动抛出异常
    • Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要使用人工创建并抛出。
    • 首先要 生成异常类对象,然后通过 throw 语句实现抛出操作(提交给Java运行环境)
    • 可以抛出的异常必须是Throwable或其子类的实例。下面的语句在编译时将会产生语法错误

自定义异常

  • 一般地,用户自定义异常类都是RuntimeException的子类
  • 自定义异常类通常需要编写几个重载的构造器
  • 自定义异常需要提供serialVersionUID
  • 自定义的异常通过throw抛出
  • 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型
  • 通过枚举创建异常https://www.bbsmax.com/A/lk5anZDqd1/

方法的重写与异常

  • 子类在重写方法时,父类方法没有声明编译时异常,则子类方法也不能声明编译时异常,子类不可以声明比父类方法大的异常;
  • 运行时异常没有这个规定;也就是子类在重写父类方法时,不管父类方法是否有声明异常,子类方法都可以声明异常;

try-with-resources 语句

try(资源1; 资源2; ...) {//(可以没有catch、finally)
//实现了 java.lang.AutoCloseable 接口的实例,都可以称之为是资源
} catch (Exception e) {

} finally {

}
posted @ 2023-03-02 16:55  Uinie  阅读(105)  评论(0)    收藏  举报