第六章:Java中的异常
6.1 异常概述
在Java编程中,异常(Exception)是指在程序运行过程中发生的非正常情况,它会中断正常的指令流。Java通过异常处理机制,使程序能够优雅地处理运行时错误,提高程序的健壮性和可靠性。
6.2 异常体系结构
Java的异常类都继承自java.lang.Throwable类,主要分为两大类:
- Error:系统级错误,通常由Java虚拟机(JVM)抛出,如
OutOfMemoryError、StackOverflowError等。这类错误一般无法通过程序处理。 - Exception:程序级异常,可分为:
- Checked Exception(受检异常):编译时检查的异常,必须被捕获或声明抛出,如
IOException、SQLException。 - Unchecked Exception(非受检异常):运行时异常,编译时不强制检查,如
NullPointerException、ArrayIndexOutOfBoundsException。
- Checked Exception(受检异常):编译时检查的异常,必须被捕获或声明抛出,如
6.3 异常处理关键字
Java提供了五个关键字来处理异常:
- try:用于包裹可能抛出异常的代码块。
- catch:用于捕获并处理特定类型的异常。
- finally:无论是否发生异常都会执行的代码块,常用于资源清理。
- throw:在方法内部手动抛出一个异常对象。
- throws:在方法声明中指明该方法可能抛出的异常类型。
6.4 try-catch-finally 基本用法
public class ExceptionDemo {
public static void main(String[] args) {
try {
// 可能抛出异常的代码
int result = 10 / 0; // 这里会抛出 ArithmeticException
System.out.println("结果:" + result);
} catch (ArithmeticException e) {
// 捕获并处理算术异常
System.out.println("发生算术异常:" + e.getMessage());
} finally {
// 无论是否发生异常都会执行
System.out.println("finally 块执行完成");
}
}
}
6.5 多重catch块
一个try块可以跟随多个catch块,用于捕获不同类型的异常。需要注意的是,catch块的顺序应该从具体到一般(子类到父类)。
try {
// 可能抛出多种异常的代码
FileInputStream fis = new FileInputStream("test.txt");
int data = fis.read();
fis.close();
} catch (FileNotFoundException e) {
System.out.println("文件未找到:" + e.getMessage());
} catch (IOException e) {
System.out.println("IO异常:" + e.getMessage());
} catch (Exception e) {
System.out.println("其他异常:" + e.getMessage());
}
6.6 try-with-resources(Java 7+)
Java 7引入了try-with-resources语句,可以自动关闭实现了AutoCloseable接口的资源,简化了资源管理代码。
try (FileInputStream fis = new FileInputStream("test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("读取文件时发生异常:" + e.getMessage());
}
6.7 自定义异常
除了使用Java内置的异常类,我们还可以创建自定义异常类来满足特定的业务需求。
// 自定义受检异常
public class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
// 自定义运行时异常
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}
// 使用示例
public class BankAccount {
private double balance;
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException("余额不足,当前余额:" + balance);
}
balance -= amount;
}
}
6.8 异常处理的最佳实践
- 不要捕获所有异常:避免使用
catch (Exception e)捕获所有异常,应该只捕获你能处理的异常。 - 不要忽略异常:空的catch块会隐藏错误,至少应该记录异常信息。
- 使用具体的异常类型:抛出和捕获尽可能具体的异常类型。
- finally块中不要抛出异常:finally块中的异常会覆盖try或catch块中的异常。
- 异常信息要明确:抛出的异常应该包含足够的信息来诊断问题。
- 考虑使用异常链:通过
initCause()或构造函数保留原始异常信息。
6.9 常见异常类型及原因
| 异常类型 | 常见原因 | 示例 |
|---|---|---|
NullPointerException | 尝试访问null对象的属性或方法 | String str = null; str.length(); |
ArrayIndexOutOfBoundsException | 数组索引越界 | int[] arr = new int[3]; arr[5] = 10; |
ClassCastException | 类型转换错误 | Object obj = "hello"; Integer num = (Integer) obj; |
NumberFormatException | 字符串转换为数字格式错误 | Integer.parseInt("abc"); |
IllegalArgumentException | 方法参数不合法 | Thread.sleep(-100); |
6.10 总结
异常处理是Java编程中的重要组成部分。合理的异常处理能够:
- 提高程序的健壮性和可靠性
- 提供清晰的错误信息和调试线索
- 确保资源的正确释放
- 分离正常逻辑和错误处理逻辑
在实际开发中,应该根据具体场景选择合适的异常处理策略,遵循最佳实践,编写出既健壮又易于维护的代码。

1450

被折叠的 条评论
为什么被折叠?



