1 异常的概念
在 Java 程序中,异常(Exception)是一种用于处理程序运行时错误的机制。异常是程序执行过程中出现的非正常情况,这些情况会中断正常的程序流程。例如:除以零、数组下标越界、空指针引用等错误。通过使用异常机制,程序可以更好地管理错误,而不是在发生错误时崩溃。
2 异常的分类
在 Java 中,异常主要分为以下两类:
2.1 检查型异常(Checked Exception)
检查型异常是在编译时由编译器检查的异常,必须使用 try-catch 块捕获,或者使用 throws 关键字进行声明。
常见的检查型异常有:
IOException(输入/输出异常)
SQLException(SQL 操作异常)
示例:读取文件时,可能会遇到文件找不到的情况,这种情况会抛出 FileNotFoundException,这是检查型异常。
2.1 非检查型异常(Unchecked Exception)
非检查型异常是在运行时抛出的异常,编译器不会强制要求处理这类异常。它们通常是由程序逻辑错误引起的。
常见的非检查型异常有:
NullPointerException(空指针异常)
ArrayIndexOutOfBoundsException(数组下标越界异常)
ArithmeticException(算术异常,如除以零)
示例:如果尝试访问 null 对象的方法,会抛出 NullPointerException。
2.3 错误(Error)
错误是指严重的系统级问题,通常不需要也不应该由应用程序捕获。例如,OutOfMemoryError(内存溢出错误)。
错误通常由 JVM 抛出,程序无法恢复。
3 异常处理机制
try-catch:捕获并处理异常。
finally:用于清理资源,无论是否抛出异常都会执行。
throws:声明异常,让调用者处理。
throw:显式抛出异常,通常用于验证输入。
自定义异常:适用于特定业务场景,增强可读性。
try-with-resources:自动管理资源,避免资源泄漏。
3.1 Java 提供了 try-catch 块来捕获和处理异常,常用的还有 finally 块来执行一些清理工作:
try {
// 可能会抛出异常的代码
} catch (异常类型 e) {
// 处理异常的代码
} finally {
// 无论是否发生异常都会执行的代码
}
示例:
public class ExceptionExample {
public static void main(String[] args) {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); // 这里会抛出 ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界异常:" + e.getMessage());
} finally {
System.out.println("无论是否发生异常,都会执行这段代码");
}
}
}
输出:
数组下标越界异常:Index 3 out of bounds for length 3
无论是否发生异常,都会执行这段代码
3.2 异常的声明和抛出
Java 中可以使用 throws 关键字在方法签名中声明异常,使用 throw 关键字显式抛出异常。
public class ExceptionThrowExample {
public static void main(String[] args) {
try {
checkAge(15);
} catch (Exception e) {
System.out.println("捕获异常: " + e.getMessage());
}
}
// 使用 throws 声明异常
public static void checkAge(int age) throws Exception {
if (age < 18) {
throw new Exception("年龄未满 18 岁");
}
}
}
输出:
捕获异常: 年龄未满 18 岁
3.3 自定义异常
Java 允许开发者创建自己的异常类,继承 Exception 或 RuntimeException。
class MyCustomException extends Exception {
public MyCustomException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
throw new MyCustomException("这是一个自定义异常");
} catch (MyCustomException e) {
System.out.println("捕获自定义异常: " + e.getMessage());
}
}
}
输出:
捕获自定义异常: 这是一个自定义异常
3.4 异常的传播
当异常发生时,如果当前方法没有处理异常,它会沿着调用栈向上传播,直到遇到处理异常的 try-catch 块。如果最终没有处理,程序会终止并输出异常的堆栈跟踪信息。
示例:
public class ExceptionPropagationExample {
public static void main(String[] args) {
methodA();
}
public static void methodA() {
methodB();
}
public static void methodB() {
int result = 10 / 0; // 这里会抛出 ArithmeticException
}
}
输出:
Exception in thread "main" java.lang.ArithmeticException:
at ExceptionPropagationExample.methodB
at ExceptionPropagationExample.methodA
at ExceptionPropagationExample.main
总结
捕获异常 可以让程序处理异常情况而不崩溃。
抛出异常 可以让异常传播到调用者,由调用者决定如何处理。
自定义异常 使得程序可以根据特定需求定义自己的错误类型。
finally 块 保证在异常处理后执行一些清理工作。
常见问题
1 Java中的异常处理机制有哪些?
try-catch:用于捕获并处理异常。
finally:无论是否发生异常,都会执行,用于资源清理。
throw:显式抛出异常。
throws:用于方法声明中,表示该方法可能会抛出异常,由调用者处理。
自定义异常:通过继承 Exception 或 RuntimeException 类,创建特定场景的异常。
try-with-resources:用于自动管理资源(从 Java 7 开始),避免资源泄漏。
2 Error和Exception的区别是什么?
Error(错误):
是 Java 中的严重问题,通常由 JVM 抛出,例如内存不足 (OutOfMemoryError)。
不建议捕获或处理,因为它们通常不可恢复。
Exception(异常):
是程序运行时出现的错误,分为检查型异常和非检查型异常。
可以使用 try-catch 块捕获和处理,常见的如 IOException、NullPointerException。
3 throw和throws的异同?
throw:
用于在方法内部显式抛出异常实例。
语法:throw new Exception(“错误信息”)。
只能用于抛出一个异常。
throws:
用于方法声明中,表示该方法可能抛出某种异常,调用者需要处理。
语法:public void method() throws Exception。
可以声明多个异常,用逗号分隔。