Java 异常处理机制提供了一种强大的机制来处理运行时错误,从而避免程序的崩溃并且能够优雅地处理错误。Java 中的异常处理由 try、catch、finally 语句组成,通过它们能够捕获并处理运行时发生的异常。
1. 异常的分类
Java 中的异常分为两类:
- 已检查异常 (Checked Exception): 编译器强制要求处理的异常,通常是由于外部环境问题导致的,如文件未找到、网络连接中断等。必须在代码中显式处理(使用
try-catch)或者声明(使用throws)。 例子:IOException、SQLException - 未检查异常 (Unchecked Exception): 也叫运行时异常,是由程序员的错误或逻辑问题引起的,编译器不强制要求处理。运行时异常通常不需要显式处理。 例子:
NullPointerException、ArrayIndexOutOfBoundsException
2. 异常的基本处理
Java 使用 try-catch 块来处理异常。当代码中可能发生异常时,可以使用 try 块包围这些代码,并使用 catch 块捕获异常进行处理。
2.1 使用 try-catch 块
public class ExceptionExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // 这里会抛出一个 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("错误:除数不能为零!");
}
}
}
在上面的代码中,try 块中的代码会执行,如果发生异常,则跳转到对应的 catch 块进行异常处理。
2.2 多个 catch 块
一个 try 块可以有多个 catch 块来处理不同类型的异常。
public class MultipleCatchExample {
public static void main(String[] args) {
try {
int[] numbers = new int[2];
numbers[10] = 25; // 这里会抛出 ArrayIndexOutOfBoundsException
} catch (ArithmeticException e) {
System.out.println("算术异常!");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界!");
}
}
}
2.3 捕获多个异常
在 Java 7 及以后版本中,可以使用管道符(|)来捕获多个异常。
public class MultipleExceptionExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // ArithmeticException
int[] numbers = new int[2];
numbers[10] = 25; // ArrayIndexOutOfBoundsException
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("发生了异常:" + e);
}
}
}
2.4 finally 块
无论是否发生异常,finally 块中的代码总会执行。finally 块通常用于清理资源(如关闭文件、数据库连接等)。
public class FinallyExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // 会抛出 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("错误:除数不能为零!");
} finally {
System.out.println("无论发生什么,finally 块总会执行!");
}
}
}
2.5 使用 throw 抛出异常
在 Java 中,可以使用 throw 关键字抛出一个异常对象。
public class ThrowExample {
public static void main(String[] args) {
try {
validateAge(15);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
public static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("年龄必须大于等于 18 岁!");
}
}
}
在上面的例子中,当年龄小于 18 时,抛出了一个 IllegalArgumentException。
2.6 自定义异常
Java 允许你创建自己的异常类,继承 Exception 或 RuntimeException 类。
// 自定义一个异常类
class AgeNotValidException extends Exception {
public AgeNotValidException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
validateAge(15);
} catch (AgeNotValidException e) {
System.out.println(e.getMessage());
}
}
public static void validateAge(int age) throws AgeNotValidException {
if (age < 18) {
throw new AgeNotValidException("年龄不符合要求,必须大于等于 18 岁!");
}
}
}
在上述例子中,AgeNotValidException 是一个自定义异常,用于检查年龄是否符合要求。
3. 异常声明 – throws
有时你可能希望将异常的处理交给调用者来处理。这时可以使用 throws 关键字在方法签名中声明异常。
import java.io.IOException;
public class ThrowsExample {
public static void main(String[] args) {
try {
readFile("file.txt");
} catch (IOException e) {
System.out.println("读取文件时发生错误:" + e.getMessage());
}
}
// 在方法签名中声明抛出异常
public static void readFile(String fileName) throws IOException {
if (fileName == null) {
throw new IOException("文件名不能为空!");
}
// 读取文件的代码...
}
}
在这个例子中,readFile 方法声明抛出 IOException 异常,调用该方法时必须处理该异常。
4. 异常的层次结构
Java 的异常类有一个层次结构,最基本的类是 Throwable,它有两个主要的子类:
- Error: 代表 JVM 层级的错误(例如内存溢出、堆栈溢出等),这些错误通常无法恢复,程序也没有能力处理。
- Exception: 代表程序级的异常,程序可以捕获并处理这些异常。
Exception 又有两个子类:
- CheckedException: 编译时异常,需要显式处理。
- UncheckedException: 运行时异常,可以不处理。
5. 总结
- 使用
try-catch块来捕获并处理异常。 finally块用于执行清理工作,无论是否发生异常。throw关键字用于抛出异常,throws关键字用于声明异常。- 可以创建自定义异常类。
- 使用
catch捕获多个异常时,可以使用|符号简化代码。
通过这种方式,Java 提供了一种结构化的异常处理机制,让我们能够编写更加健壮和可维护的代码。更多详细内容请关注其他相关文章。