Java异常处理机制与自定义异常实现
异常类层次结构
在Java编程中,异常处理是构建健壮应用程序的关键组成部分。Java采用面向对象的方式管理异常,当程序执行过程中发生错误时,会创建异常对象并传递给运行时系统。
异常产生原因
Java程序中出现异常通常源于以下几种情况:
- JVM内部错误引发的系统异常
- 程序逻辑错误导致的运行时异常,如空指针引用、数组越界等
- 通过throw语句显式触发的异常,用于向调用者传递特定信息
常见异常场景包括:
- 用户输入无效数据
- 请求的文件不存在
- 网络连接中断或内存溢出
异常类型分类
Java异常主要分为三类:
-
检查异常(Checked Exceptions):通常由用户错误或外部问题引起,程序员无法预见,必须在编译时处理。例如:文件不存在异常。
-
运行时异常(Runtime Exceptions):可由程序员避免的异常,编译器不强制要求处理。例如:空指针异常。
-
错误(Errors):不是异常,而是超出程序员控制的问题,通常不处理。例如:栈溢出错误。
异常类继承体系
所有异常类都继承自java.lang.Exception类,而Exception又是Throwable类的子类。Throwable还有一个子类Error,用于表示严重的系统错误。
异常类的两个主要子类:
- IOException:处理输入输出相关异常
- RuntimeException:处理程序运行时产生的异常
常用异常方法
Throwable类提供了几个关键方法:
- printStackTrace():输出异常类型、性质、调用栈信息
- getMessage():获取异常的具体描述信息
- toString():返回异常的字符串表示
常见异常列表
非检查异常:
| 异常类 | 描述 |
|---|---|
| ArithmeticException | 算术运算错误,如除零操作 |
| ArrayIndexOutOfBoundsException | 数组索引越界 |
| NullPointerException | 空对象引用 |
| IllegalArgumentException | 非法参数传递 |
| NumberFormatException | 数字格式转换错误 |
检查异常:
| 异常类 | 描述 |
|---|---|
| ClassNotFoundException | 类未找到 |
| IOException | 输入输出异常 |
| SQLException | 数据库访问异常 |
| InterruptedException | 线程中断异常 |
异常处理关键字
throws关键字
throws用于声明方法可能抛出的异常,表示该方法不处理这些异常,而是将异常处理责任交给调用者。
语法格式:
返回值类型 方法名(参数列表) throws 异常类型1, 异常类型2 {
// 方法实现
}
使用throws的典型场景:
- 当前方法不知道如何处理特定异常
- 希望将异常处理责任向上传递
- 调用者需要根据异常类型采取不同处理策略
throw关键字
throw用于显式抛出异常对象,执行throw语句后,当前方法会立即终止,异常对象会被传递到调用栈的上一层。
if (参数 < 0) {
throw new IllegalArgumentException("参数不能为负数");
}
异常捕获机制
try-catch-finally结构
try-catch-finally是Java异常处理的核心结构:
try {
// 可能抛出异常的代码
} catch (异常类型1 变量名) {
// 处理异常类型1的代码
} catch (异常类型2 变量名) {
// 处理异常类型2的代码
} finally {
// 无论是否发生异常都会执行的代码
}
执行规则:
- try块中没有异常:顺序执行try块和finally块,跳过catch块
- try块中抛出异常:执行匹配的catch块,然后执行finally块
- 多个catch块:按顺序匹配,父类异常的catch块必须在子类之后
- finally块:总是执行(除非调用System.exit())
代码示例
public class ExceptionDemo {
private static String result = "";
public static void processValue(int value) {
try {
if (value == 1) {
throw new IllegalStateException("值不能为1");
}
result += "A";
} catch (Exception e) {
System.out.println(e.getMessage());
result += "M";
return;
} finally {
result += "C";
}
result += "G";
}
public static void main(String[] args) {
processValue(0);
processValue(1);
System.out.println(result);
}
}
输出结果:
值不能为1
ACGMC
自定义异常
创建自定义异常类
自定义异常需要遵循以下规则:
- 所有异常必须继承自Throwable类
- 检查异常需继承Exception类
- 运行时异常需继承RuntimeException类
// 检查异常
class BusinessException extends Exception {
public BusinessException(String message) {
super(message);
}
}
// 运行时异常
class SystemRuntimeException extends RuntimeException {
public SystemRuntimeException(String message) {
super(message);
}
}
自定义异常使用示例
public class CustomExceptionDemo {
public static void main(String[] args) {
try {
validateInput(-5);
} catch (BusinessException e) {
System.out.println("捕获到业务异常: " + e.getMessage());
}
try {
checkSystemCondition(10);
} catch (SystemRuntimeException e) {
System.out.println("捕获到系统异常: " + e.getMessage());
}
}
// 抛出检查异常
public static void validateInput(int value) throws BusinessException {
if (value < 0) {
throw new BusinessException("输入值不能为负数");
}
System.out.println("输入值有效: " + value);
}
// 抛出运行时异常
public static void checkSystemCondition(int threshold) {
if (threshold > 5) {
throw new SystemRuntimeException("系统参数超出阈值: " + threshold);
}
System.out.println("系统参数正常: " + threshold);
}
}
输出结果:
捕获到业务异常: 输入值不能为负数
系统参数正常: 10
自定义异常类应遵循命名规范,通常以"Exception"作为后缀,如"UserNotFoundException"、"InvalidParameterException"等,以清晰表达异常的用途。
通过合理使用异常处理机制和自定义异常,可以显著提高Java程序的健壮性和可维护性。