异常和异常处理介绍

异常是程序执行时发生的错误。考虑下面的 Java 程序,它划分两个整数。

class Division {
    public static void main(String[] args) {
 
        int a, b, result;
 
        Scanner input = new Scanner(System.in);
        System.out.println("Input two integers");
 
        a = input.nextInt();
        b = input.nextInt();
 
        result = a / b;
 
        System.out.println("Result = " + result);
    }
}

现在我们编译并执行上面的代码,并看到尝试除以零的输出:

Input two integers
7 0
Exception in thread "main" java.lang.ArithmeticException: / by zero 
    at Division.main(Disivion.java:14)

除以零是一个无效操作,它将产生一个不能表示为整数的值。Java 通过抛出异常来解决这个问题。在这种情况下,异常是 ArithmeticException 类的一个实例。

注意: 有关创建和读取堆栈跟踪的示例说明了两个数字后的输出含义。

异常的效用是它允许的流程控制。不使用异常,这个问题的典型解决方案可能是首先检查是否 b == 0

class Division {
    public static void main(String[] args) {
 
        int a, b, result;

        Scanner input = new Scanner(System.in);
        System.out.println("Input two integers");
 
        a = input.nextInt();
        b = input.nextInt();
 
        if (b == 0) {
            System.out.println("You cannot divide by zero.");
            return;
        }

        result = a / b;
 
        System.out.println("Result = " + result);
    }
}

这会将消息 You cannot divide by zero. 打印到控制台,并在用户尝试除以零时以优雅的方式退出程序。通过异常处理处理此问题的等效方法是用 try-catch 块替换 if 流程控制:

...

a = input.nextInt();
b = input.nextInt();
 
try {
    result = a / b;
}
catch (ArithmeticException e) {
    System.out.println("An ArithmeticException occurred. Perhaps you tried to divide by zero.");
    return;
}
 
...  

try catch 块执行如下:

  1. 开始执行 try 块中的代码。
  2. 如果 try 块中发生异常,则立即中止并检查 catch 块是否捕获此异常 (在这种情况下,当 Exception 是 ArithmeticException 的实例时)。
  3. 如果捕获到异常,则将其分配给变量 e 并执行 catch 块。
  4. 如果 trycatch 块已完成(即代码执行期间未发生未捕获的异常),则继续执行 try-catch 块下面的代码。

通常认为将异常处理用作应用程序的正常流控制的一部分是良好的做法,否则行为将是未定义或意外的。例如,代替在方法失败时返回 null,通常更好的做法是抛出异常,以便使用该方法的应用程序可以通过上述类型的异常处理为该情境定义自己的流控制。在某种意义上,这解决了必须返回特定类型的问题,因为可以抛出多种异常中的任何一种来指示发生的特定问题。 **

有关如何以及如何不使用异常的更多建议,请参阅 Java 陷阱 - 异常使用