[Day25] CH12:凡事总有例外——例外处理

还记得我们在学习条件判断时写过两数相除的程序吗?那时候遇到除数为 0 时,我们是使用 if 来判断,但如果今天发生其他错误,像是输入值不是数字那怎麽办呢?好在 Java 提供了例外(Exception)处理机制,协助我们捕捉程序执行时的错误,在例外发生时,可以加入相对应的措施,使程序可以正常结束,今天我们就要很粗浅的认识例外处理。

看到之前第一个两数相除的程序,试试看如果除数为 0 会发生什麽事。

import java.util.Scanner;

public class Division3 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter first number: ");
        int num1 = sc.nextInt();
        System.out.print("Enter second number: ");
        int num2 = sc.nextInt();
        int quotient = num1 / num2;
        System.out.printf("Quotient: %d%n", quotient);
        sc.close();
    }
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Division3.main(Division3.java:11)

果不其然发生错误了!Java 告诉你发生了 ArithmeticException,/ by zero 指出例外是因为试图除以 0 而发生。 Java 不允许整数运算除以 0,当发生此情形时,就会抛出 ArithmeticException。但如果是浮点数的话则会出现其他答案,大家可以试试看。除此之外,我们还可以看到在第 11 行(quotient = num1 / num2;)的地方时例外的抛出点。

我们再试试看如果除数不为数字会发生什麽事。

Exception in thread "main" java.util.InputMismatchException
    at java.base/java.util.Scanner.throwFor(Scanner.java:939)
    at java.base/java.util.Scanner.next(Scanner.java:1594)
    at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
    at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
    at Division3.main(Division3.java:10)

这次发生了 InputMismatchException,从最後一行看出发生例外的地方在第 10 行,再往上看可以发现例外是发生在 nextInt 方法。

那我们要怎麽解决呢?首先来认识例外处理的语法:

try{
    //检查是否有例外产生,若有就丢出例外
}
catch(例外类型 e){
    //处理不同例外类型,可有多个 catch 区块
}
finally{
    //可有可无,用来善後工作,无论例外是否产生皆会执行
}

只要有 try 就需要有 catch,finally 则不一定要有。

我们将以上程序改成若发生例外,则持续输入,直到成功运算为止。

import java.util.InputMismatchException;
import java.util.Scanner;

public class Division3 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        boolean flag = true;    //判断是否需要继续读入
        do{
            try{
                System.out.print("Enter first number: ");
                int num1 = sc.nextInt();
                System.out.print("Enter second number: ");
                int num2 = sc.nextInt();
                int quotient = num1 / num2;
                System.out.printf("Quotient: %d%n",quotient);
                flag = false;
                sc.close();
            }
            catch(InputMismatchException inputMismatchException){
                System.err.printf("%nException: %s%n", inputMismatchException);
                sc.nextLine();  //忽略错误的输入
                System.out.println("Please enter integers.");
                System.out.println();
            }
            catch(ArithmeticException arithmeticException){
                System.err.printf("%nException: %s%n", arithmeticException);
                System.out.println("除数不得为 0");
                System.out.println();
            }
        }while(flag);
    }
}

首先将 InputMismatchException 类别汇入,ArithmeticException 类别不需要汇入。一开始宣告了 flag 判断是否需要继续读入,若是发生例外则 flag 始终为 true,继续读入,直到输入值为有效值为止。

由上述的例子可以看到,一个 try 能有多个 catch,在输入不为数字时,nextInt 方法就会抛出 InputMismatchException,而当除数为 0 时,在两数相除时就会抛出 ArithmeticException。在 catch 中,可以看到使用了 System.err 来输出错误讯息,而因为 flag 为 true 程序会继续执行。

内建例外

在 Java 中属於 Throwable 类别,其子类别分为以下两种:

  • Error 类别

    专门用來处理严重影响程序执行的错误,通常不会设计程序码去捕捉。

  • Exception 类别

    包含有一般性的例外,这些例外通常在捕捉到之後便可做妥善的处理,我们将之称为例外,这些類别则称为例外類别,以下为常见的例外:

例外 说明
ArithmeticException 算术运算式的错误,例如除以 0。
ArrayIndexOutOfBoundsException 阵列索引超过界限。
ArrayStoreException 将型态不符的物件设定为物件阵列的元素。
IllegalArgumentException 呼叫方法时引數错误。
NullPointerException 物件值为 null 产生的例外

除了内建例外,我们也可以自订例外,但这里我们并不会继续介绍,例外处理若要全部介绍完可能需要三天三夜 XD,不过因为时间有限,所以本教学就只介绍到这里,让初学者可以简单认识例外并使用,剩下的时间我们会认识更多东西。


<<:  图的连通 (5)

>>:  33岁转职者的前端笔记-DAY 25 JavaScript 回圈语法笔记

Day 1 - JavaScript 的变数与基本资料型态

废话不多说~直接进入正题 变数(Variable) 变数就像一个箱子,拿来装资料,且所有变数都只能出...

第 12 天 小有成果保持练习( leetcode 043 )

https://leetcode.com/problems/multiply-strings/ M...

难搞的字串符

字符串编码转换 在 python3.x 中,默认采用编码格式为UTF-8 在 python 中,有两...

Day 24 - Input filtering 相关攻击

出於书本 Chapter 14. Web sites and Applications 网站与网路应...

Day06【JS】「...」展开运算符 & 其余运算符

「展开运算符」与「其余运算符」, 两者的表示方式都是 ..., 以下分别说明。 展开运算符 展开运算...