【Java异常】面试官问你Java中的异常,这篇就够了
文章目录
1. 什么是Java异常?2. Java异常层次结构3. 常见Java异常类型及处理方法(面试常问)3.1 NullPointerException(空指针异常)3.2 IndexOutOfBoundsException(数组索引越界异常)3.3 ClassNotFoundException(类未找到异常)3.4 NumberFormatException(数字格式异常)3.5 IllegalArgumentException(非法参数异常)3.6 ClassCastException(类转换异常)3.7 FileNotFoundException(文件未找到异常)3.8 NoSuchMethodException(方法不存在异常)
4. 异常处理技巧4.1 使用try-catch块4.2 使用finally块4.3 使用try-with-resources语句4.4 多重catch块
5. 异常处理最佳实践
1. 什么是Java异常?
Java异常是在程序执行过程中发生的异常事件,它会中断程序的正常流程。异常可以是由于用户输入错误、硬件故障、网络问题等各种原因引起的。Java使用异常处理机制来处理这些运行时错误,使得程序能够更加健壮和可靠。
2. Java异常层次结构
Java的所有异常都是java.lang.Throwable类的子类。Throwable有两个直接子类:Error和Exception。
Error:表示严重的问题,通常是不可恢复的。例如OutOfMemoryError。Exception:表示可以被程序处理的问题。又分为两类:
检查型异常(Checked Exceptions):必须在代码中显式处理或声明抛出。非检查型异常(Unchecked Exceptions):运行时异常,不需要显式处理。
3. 常见Java异常类型及处理方法(面试常问)
3.1 NullPointerException(空指针异常)
这可能是Java中最常见的异常之一。当试图使用一个值为null的对象引用时,就会抛出这个异常。
示例:
String str = null;
System.out.println(str.length()); // 抛出NullPointerException
防范措施:
在使用对象之前进行null检查使用Java 8引入的Optional类来处理可能为null的值
3.2 IndexOutOfBoundsException(数组索引越界异常)
当试图访问数组中不存在的索引时,会抛出此异常。
示例:
int[] arr = new int[5];
System.out.println(arr[5]); // 抛出ArrayIndexOutOfBoundsException
防范措施:
在访问数组元素前检查索引是否有效使用集合类(如ArrayList)代替数组,它们提供了更安全的操作方法
3.3 ClassNotFoundException(类未找到异常)
当试图加载类,但找不到相应的类定义时,就会抛出这个异常。
示例:
Class.forName("com.example.NonExistentClass"); // 抛出ClassNotFoundException
防范措施:
仔细检查类名的拼写确保类路径(classpath)设置正确
3.4 NumberFormatException(数字格式异常)
当试图将一个字符串转换为数字,但该字符串不能表示一个有效的数字时,会抛出此异常。
示例:
int num = Integer.parseInt("123abc"); // 抛出NumberFormatException
防范措施:
在转换之前验证字符串的格式使用正则表达式检查字符串是否只包含数字
3.5 IllegalArgumentException(非法参数异常)
当方法接收到一个不适当的参数时,会抛出这个异常。
示例:
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
this.age = age;
}
防范措施:
在方法开始处验证参数的有效性为公共API提供清晰的文档,说明参数的有效范围
3.6 ClassCastException(类转换异常)
当试图将对象强制转换为不是其子类型的类时,会抛出ClassCastException。这是一个运行时异常,通常由于程序逻辑错误导致。
示例:
Object obj = new Integer(123);
String str = (String) obj; // 抛出ClassCastException
防范措施:
在进行类型转换之前,使用instanceof运算符检查对象的实际类型使用泛型来避免不必要的类型转换
3.7 FileNotFoundException(文件未找到异常)
当试图访问一个不存在的文件时,会抛出FileNotFoundException。这是一个检查型异常,需要显式处理。
示例:
try {
FileInputStream fis = new FileInputStream("nonexistent.txt");
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
}
防范措施:
在访问文件之前,使用File类的exists()方法检查文件是否存在使用相对路径时,确保路径是相对于正确的基础目录在处理文件操作时,始终使用try-catch块或throws声明
3.8 NoSuchMethodException(方法不存在异常)
当试图通过反射调用一个不存在的方法时,会抛出NoSuchMethodException。这是一个检查型异常。
示例:
try {
Class> cls = Class.forName("java.lang.String");
Method method = cls.getMethod("nonexistentMethod");
} catch (NoSuchMethodException e) {
System.out.println("Method not found: " + e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("Class not found: " + e.getMessage());
}
防范措施:
在使用反射调用方法之前,仔细检查方法名称和参数类型如果可能,优先使用编译时检查而不是反射在使用反射时,总是捕获并适当处理NoSuchMethodException
4. 异常处理技巧
4.1 使用try-catch块
try-catch是Java中处理异常的基本方式。将可能抛出异常的代码放在try块中,然后在catch块中处理异常。
try {
// 可能抛出异常的代码
} catch (ExceptionType e) {
// 异常处理代码
}
4.2 使用finally块
finally块中的代码无论是否发生异常都会执行,通常用于资源清理。
try {
// 可能抛出异常的代码
} catch (Exception e) {
// 异常处理代码
} finally {
// 清理代码,总是执行
}
4.3 使用try-with-resources语句
Java 7引入的try-with-resources语句可以自动关闭实现了AutoCloseable接口的资源。
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
// 异常处理
}
4.4 多重catch块
可以使用多个catch块来处理不同类型的异常。
try {
// 可能抛出多种异常的代码
} catch (IOException e) {
// 处理IO异常
} catch (SQLException e) {
// 处理SQL异常
} catch (Exception e) {
// 处理其他类型的异常
}
5. 异常处理最佳实践
不要捕获顶层异常: 避免直接捕获Exception或Throwable,而应该捕获具体的异常类型。
不要忽视异常: 始终在catch块中至少记录异常信息,不要使用空的catch块。
及时释放资源: 使用try-with-resources或在finally块中释放资源。
抛出有意义的异常: 当抛出异常时,提供有意义的错误消息和相关的上下文信息。
使用自定义异常: 为特定的业务逻辑错误创建自定义异常类,以提高代码的可读性。
合理使用checked和unchecked异常: 对于调用者应该处理的错误使用checked异常,对于程序错误使用unchecked异常。
记录异常: 使用日志框架(如Log4j或SLF4J)来记录异常,而不是简单地打印到控制台。