Java异常类层次结构图:
在 Java 编程中,异常(Exception) 是我们无法避免的一个话题。无论是文件读取失败、网络连接中断还是空指针访问,异常处理都是确保程序健壮性和稳定性的关键。
Java 的异常体系基于 Throwable
类及其子类。Throwable
是所有异常的根类,它有两个重要的子类:
OutOfMemoryError
)、栈溢出(StackOverflowError
)等。这类错误通常由 JVM 抛出,程序不应尝试捕获或处理它们。
FileNotFoundException
)、类未找到(ClassNotFoundException
)等。RuntimeException
,编译器不要求处理,如空指针访问(NullPointerException
)、数组越界(ArrayIndexOutOfBoundsException
)等。类型 | 描述 | 示例 |
---|---|---|
非运行时异常 | 编译器强制要求捕获或声明抛出的异常 | FileNotFoundException, IOException |
运行时异常 | 编译器不强制要求处理的异常,通常由程序逻辑错误引发 | NullPointerException, ArrayIndexOutOfBoundsException |
异常处理的核心是 try-catch
语句块。它允许你在代码中捕获并处理可能发生的异常。
try {
// 可能抛出异常的代码
} catch (ExceptionType1 e1) {
// 处理异常类型1的逻辑
} catch (ExceptionType2 e2) {
// 处理异常类型2的逻辑
} finally {
// 可选的finally块,无论是否发生异常都会执行
}
catch
块来处理不同类型的异常。public class FileReaderExample {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (FileNotFoundException e) {
System.out.println("文件未找到:" + e.getMessage());
} catch (IOException e) {
System.out.println("读取文件时发生错误:" + e.getMessage());
} finally {
if (fis != null) {
try {
fis.close(); // 确保资源被正确关闭
} catch (IOException e) {
System.out.println("关闭文件流时发生错误:" + e.getMessage());
}
}
}
}
}
除了捕获异常,Java 还允许你通过 throw
语句手动抛出异常。你可以根据需要抛出任何类型的异常对象。
throw new ExceptionType("异常信息");
public void divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("除数不能为零!");
}
System.out.println(a / b);
}
如果一个方法可能抛出异常,但不想在方法内部进行处理,可以使用 throws
关键字将异常传递给调用者。
public void methodName() throws ExceptionType {
// 方法体
}
public void readFile(String filePath) throws IOException {
FileInputStream fis = new FileInputStream(filePath);
// 其他代码...
}
注意:对于未检查异常(如
NullPointerException
),不需要使用throws
声明。
在处理文件、数据库连接等外部资源时,确保资源的正确关闭非常重要。try-with-resources
语句可以帮助我们自动管理资源。
public void readFileWithTryWithResources(String filePath) {
try (FileInputStream fis = new FileInputStream(filePath)) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
System.out.println("读取文件时发生错误:" + e.getMessage());
}
}
有时我们需要定义自己的异常类来处理特定的业务逻辑错误。自定义异常类通常继承自 Exception
或 RuntimeException
。
public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public void validateAge(int age) throws InvalidAgeException {
if (age < 0 || age > 150) {
throw new InvalidAgeException("年龄无效:" + age);
}
System.out.println("年龄有效:" + age);
}
A: Java 中的异常主要分为两大类:
OutOfMemoryError
)、栈溢出(StackOverflowError
)。这类错误通常由 JVM 抛出,程序不应尝试捕获或处理。FileNotFoundException
)、类未找到(ClassNotFoundException
)。NullPointerException
)、数组越界(ArrayIndexOutOfBoundsException
)。try-with-resources
语句?A: try-with-resources
是 Java 7 引入的一种简化资源管理的方式。它允许你在 try
语句中声明要使用的资源,并在 try
块结束后自动关闭这些资源。例如:
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 使用资源
} catch (IOException e) {
// 处理异常
}
无需显式调用 close()
方法,JVM 会自动在 try
块结束后关闭资源。
finally
块的作用是什么?A: finally
块用于定义无论是否发生异常都会执行的代码块。通常用于释放资源,确保资源的正确关闭。即使在 try
块中有 return
语句,finally
块也会执行。
如果 finally
块中也有 return
语句,它会覆盖 try
块中的返回值。例如:
try {
return "a";
} finally {
return "b"; // 返回 "b"
}
throws
关键字?A: 当一个方法可能抛出异常,但不想在方法内部进行处理时,可以使用 throws
关键字将异常传递给调用者。对于未检查异常(如 NullPointerException
),不需要使用 throws
声明。
public void readFile(String filePath) throws IOException {
FileInputStream fis = new FileInputStream(filePath);
// 其他代码...
}
A: 在 catch
块中,捕获异常的顺序非常重要。你应该按照从具体到一般的顺序捕获异常。例如:
try {
// 可能抛出异常的代码
} catch (FileNotFoundException e) {
// 捕获具体的 FileNotFoundException
} catch (IOException e) {
// 捕获更广泛的 IOException
}
如果你先捕获了 IOException
,那么 FileNotFoundException
将永远不会被捕获,因为它已经是 IOException
的子类。
在这篇文章中,我们详细讨论了 Java 异常的基础概念、异常处理机制以及常见的面试题。掌握异常处理不仅能帮助你编写更加健壮的代码,还能在面试中应对各种与异常相关的问题。
Error
和 Exception
两大类。try-catch
语句块捕获和处理异常,使用 throws
关键字声明异常,使用 finally
块确保资源的正确关闭。