异常处理(1)

标签:通知   数据   特定   登录   rgs   main   执行   占用   strong   

实验介绍

由于 Java 应用程序在运行的过程中,总难免会发生一些异常,所以异常处理是我们在编写代码时必须要考虑的一项工作。所谓异常,是指程序在运行时发生的错误或者不正常的情况。异常对程序员来说是一件很麻烦的事情,需要进行检测和处理。但 Java 语言非常人性化,它可以自动检测异常,并对异常进行捕获,然后通过相应的机制对异常进行处理。本章将详细讲解 Java 处理异常的知识。

实验知识点

  • 异常处理方式
  • 抛出异常
  • 自定义异常

异常概述

在程序设计里,异常处理是指提前编写程序处理可能发生的意外。如聊天工具需要连接网络,首先就是检查网络,对网络的各个程序进行捕获,然后根据各种情况编写程序。如果登录聊天系统后突然发现没有登录网络,那么异常可以向用户提示“网络有问题,请检查联网设备”之类的提醒,这种提醒就是异常处理的工作。

认识异常

在编程过程中,首先应当尽可能避免发生错误和异常,对于不可避免、不可预测的情况再考虑异常发生时如何处理。Java 中的每一个异常都是一个对象。Java 的运行时环境将按照这些异常所属的类型进行处理,Java 中的异常类型有很多,几乎每种异常类型都对应一个类(class)。

究竟异常的对象是在哪里创建的呢?异常主要有两个来源,一是 Java 运行时环境自动抛出系统生成的异常,而不管程序员是否已经对其进行了捕获和处理,比如除数为 0 这样的异常,只要发生就一定会抛出。二是程序员抛出的异常,这个异常可以是程序员自己定义的,也可以是 Java 语言自带的,并使用 throw 关键字抛出异常,这种异常处理通常用来向调用者汇报一些出错信息。异常是针对方法来说的,抛出、声明抛出、捕获和处理异常都是在方法中进行的。

在 Java 中,异常处理通过 try、catch、throw、throws、finally 这 5 个关键字进行管理。这 5 个关键字的具体说明如下所示。

  • try:它里面放置可能引发异常的代码。
  • catch:后面对应异常类型和一个代码块。它表明该 catch 块是用于处理这种类型的代码块,可以有多个 catch 块。
  • finally:主要用于回收在 try 块里打开的物理资源(如数据库连接、网络连接和磁盘文件),异常机制保证 finally 块总是被执行。只有 finally 块执行完成之后,才会执行 try 或者 catch 块中的 return 或者 throw 语句,如果 finally 中使用了 return 或者 throw 等终止方法的语句,则就不会跳回,直接停止。
  • throw:用于抛出一个实际的异常。它可以单独作为语句来抛出一个具体的异常对象。
  • throws:用在方法签名中,用于声明该方法可能抛出的异常。

Java 处理异常的语法结构通常如下所示。

try{
      程序代码
}catch(异常类型 1 异常的变量名 1)
{
      程序代码
}catch(异常类型 2 异常的变量名 2)
{
      程序代码
}finally
{
      程序代码
}

Java 提供的异常处理类

在 Java 中有一个 lang 包,在此包里面有一个专门处理异常的类——Throwable,此类是所有异常的父类,Java 中所有的异常类都是它的子类。其中 Error 和 Exception 这两个类十分重要,用得也较多。前者用来定义通常情况下不希望被捕获的异常,而后者是程序能够捕获的异常情况。Java 中常用异常类的信息如下表所示。
技术图片

异常处理方式

Java 的异常处理可以让程序具有更好的容错性,程序更加健壮。当程序运行出现意外情形时,系统会自动生成一个 Exception 对象来通知程序,从而实现「业务功能代码」和「错误处理代码」分离,提供更好的可读性。Java 中异常的处理方式有 try/catch 捕获异常、throws 声明异常和 throw 抛出异常等,在出现异常后可以使用上述方式直接捕获并处理。

try...catch 语句

在编写 Java 程序时,需要处理的异常一般是放在 try 代码块里,然后创建 catch 代码块。在 Java 语言中,用 try...catch 语句来捕获异常的语法格式如下所示。

try {
    可能会出现异常情况的代码
}catch (SQLException e) {
    处理操纵数据库出现的异常
}catch (IOException e) {
   处理操纵输入流和输出流出现的异常
}

以上代码中的 try 块和 catch 块后的 {...} 都是不可以省略的。当程序操纵数据库出现异常时,Java 虚拟机将创建一个包含异常信息 SQLException 对象。catch (SQLException e) 语句中的引用变量 e 引用这个 SQLException 对象。上述格式的执行流程如下所示。

1、如果执行 try 块中的业务逻辑代码出现异常,则系统自动生成一个异常对象,该异常对象提交给 Java 运行环境,这个过程称为抛出(throw)异常。
2、当 Java 运行环境收到异常对象时,它会寻找能处理该异常对象的 catch 块,如果找到合适的 catch 块并把该异常对象交给 catch 块来处理,那这个过程称为捕获(catch)异常;如果 Java 运行时环境找不到捕获异常的 catch 块,则运行时环境终止,Java 程序也将退出。

新建 ExceptionOne.java 文件,编写以下代码。

public class ExceptionOne {
    public static void main(String args[]) {
        int x, y; // 定义 int 类型变量 x 和 y
        try {
            x = 0; // 为变量 x 赋值
            y = 5 / x; // 为变量 y 赋值
            System.out.println("需要检验的程序");
        } catch (ArithmeticException e) {
            System.out.println("发生了异常,分母不能为零");
        }
        System.out.println("程序运行结束");
    }
}

上面实例代码存在明显的错误,因为算术表达式中的分母为零,我们都知道除法运算中分母不能为零,这段代码需要放在 try 代码块里,然后通过 catch 里的代码对它进行处理。

在控制台中执行以下命令编译并运行程序。

java ExceptionOne.java

执行后的结果如下图所示。
技术图片

上面这个代码是用户自己编写对它进行处理的,实际上这个代码可以交给系统进行处理。

处理多个异常

在 Java 程序中经常需要面对同时处理多个异常的情况,下面通过一个具体的实例代码讲解如何处理多个异常。

新建 ExceptionTwo.java 文件,编写以下代码。

public class ExceptionTwo {
    public static void main(String args[]) {
        int[] a = new int[5]; // 定义 int 类型数组 a, 设置最大索引值为 5
        try {
            a[6] = 123; // 试图赋值索引值为 6 的元素值是 123,会出错
            System.out.println("需要检验的程序");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("发生了 ArrayIndexOutOfBoundsException 异常");
        } catch (ArithmeticException e) {
            System.out.println("发生了 ArithmeticException 异常");
        } catch (Exception e) {
            System.out.println("发生了 Exception 异常");
        }
        System.out.println("结束");
    }
}

在上述代码中定义了一个 int 类型的数组 a,我们猜测这个程序可能会发生 3 个异常。

在控制台中执行以下命令编译并运行程序。

java ExceptionTwo.java

执行后的结果如下图所示。
技术图片

finally 语句

在 Java 语言中,实现异常处理的完整语法结构如下所示。

try{
     //业务实现逻辑
     ...
}
catch(SubException e){
     //异常处理块 1
     ...
}
catch(SubException2 e){
     //异常处理块 2
     ...
}
     ...
finally{
    //资源回收块
    ...
}

对于上述语法结构,读者需要注意如下 5 点。

1、只有 try 块是必需的,也就是说如果没有 try 块,则不会有后面的 catch 块和 finally 块。
2、catch 块和 finally 块都是可选的,但 catch 块和 finally 块至少应出现一个,也可以同时出现。
3、可以有多个 catch 块,捕获父类异常的 catch 块必须位于捕获子类异常的后面。
4、不能只有 try 块,既没有 catch 块也没有 finally 块。
5、多个 catch 块必须位于 try 块之后,finally 块必须位于所有 catch 块之后。

由此可见,在使用 try...catch 处理异常时可以加上关键字 finally,它可以增大处理异常的功能,它究竟有什么作用呢?不管程序有无异常发生都将执行 finally 块中的内容,这使得一些不管在任何情况下都必须执行的步骤可以执行,这样可保证程序的健壮性。

由于异常会强制中断正常流程,所以这会使某些不管在任何情况下都必须执行的步骤被忽略,从而影响程序的健壮性。例如老管开了一家小店,店里上班的正常流程为:每天上午 9 点开门营业,工作 8 小时,下午 5 点关门下班。异常流程为:老管在工作时突然感到身体不适,提前下班。我们可以编写如下 work() 方法表示老管的上班情形。

public void work()throws LeaveEarlyException {
  try{
     9 点开门营业;
     每天工作 8 小时;//可能会抛出 DiseaseException 异常
     下午 5 点关门下班;
  }catch(DiseaseException e){
     throw new LeaveEarlyException();
  }
}

假如老管在工作时突然感到身体不适,提前下班,那么流程会跳转到 catch 代码块。这意味着关门的操作不会被执行,这样的流程显然是不安全的,必须确保关门这个操作在任何情况下都会执行。在程序中应该确保占用的资源被释放,比如及时关闭数据库连接,关闭输入流或者输出流。finally 代码块能保证特定的操作总会执行,其语法格式如下所示。

public void work()throws LeaveEarlyException {
  try{
     9 点开门营业;
     每天工作 8 小时;//可能会抛出 DiseaseException 异常
  }catch(DiseaseException e){
     throw new LeaveEarlyException();
  }finally{
     下午 17 点关门下班;
  }
}

由此可见,在 Java 中,不管 try 代码块中是否出现异常,程序都会执行 finally 代码块。请看下面实例的具体演示代码。

新建 ExceptionThree.java 文件,编写以下代码。

public class ExceptionThree {
    public static void main(String args[]) {
        try {
            int age = Integer.parseInt("25L");// 抛出异常
            System.out.println("输出 1");
        } catch (NumberFormatException e) {
            int b = 8 / 0;
            System.out.println("请输入整数年龄");
            System.out.println("错误" + e.getMessage());
        } finally {
            System.out.println("输出 2");
        }
        System.out.println("输出 3");
    }
}

执行后的结果如下图所示。
技术图片

技术图片

异常处理(1)

标签:通知   数据   特定   登录   rgs   main   执行   占用   strong   

原文地址:https://www.cnblogs.com/sakura579/p/14231869.html

版权声明:完美者 发表于 2021-01-07 11:58:51。
转载请注明:异常处理(1) | 完美导航

暂无评论

暂无评论...