Java之异常处理

261 阅读2分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。

什么是异常

在Java中,异常可以看做是导致程序无法正常运行的事件,常见的异常有NullPointerException,IndexOutOfBoundsException,OutOfMemoryError等等。这些事件可能发生在编译期,也可能发生在运行时。

Java异常继承层次结构如下图所示: java-exceptions-hierarchy-example.png

需要指出的是,这里所说的异常,并不单单指Exception,还包括Error,二者都继承了Throwable类。

Exception和Error有什么不同呢?简单地说,Exception是可以通过编写代码来进行处理的,使得程序可以继续执行下去;而Error是无法通过代码来进行处理的。举个例子,Exception中像最常见的NullPointerException,通过try-catch语句对异常进行捕获后,程序是可以继续运行下去的;而Error中常见的OutOfMemoryError,StackOverflowError等,当它们发生时,是无法使用代码处理、使得程序继续运行下去的。

Exception又可以进一步划分为Checked Exception和RuntimeException。Checked Exception发生在编译期,必须用代码显式地进行处理,否则无法通过编译。最常见的例子是在打开文件时需要用try-catch来捕获异常。而RuntimeException发生在运行时,不需要用代码显式地处理,最常见的是NullPointerException。

Exception处理

try-catch-finally

try-catch-finally基本使用如下所示:

try {
   // Protected code
} catch (ExceptionType e) {
   // Catch block
} finally {
   // The finally block always executes.
}

Protected code代表可能会抛出Exception的代码,ExceptionType表示我们想要捕获的Exception类型,Catch block代表对异常的处理代码,finally中的代码总会执行,常用来释放资源。

如果想捕获多个异常,可以用下面的代码:

try {
   // Protected code
} catch (ExceptionType1 e1) {
   // Catch block
} catch (ExceptionType2 e2) {
   // Catch block
} catch (ExceptionType3 e3) {
   // Catch block
}finally {
   // The finally block always executes.
}

throws & throw

如果一个方法没有捕获到一个检查性异常或者throw抛出的异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。

import java.io.*;
public class className {

   public void deposit(double amount) throws RemoteException {
      // Method implementation
      throw new RemoteException();
   }
   // Remainder of class definition
}

自定义异常

如果要自定义Checked Exception,那么类需要继承Exception;如果要自定义runtime exception,那么类需要继承RuntimeException。一个checked Exception的例子如下:

public class InsufficientFundsException extends Exception {
   private double amount;  
   public InsufficientFundsException(double amount) {
      this.amount = amount;
   }
   
   public double getAmount() {
      return amount;
   }
}