Java-异常类
一、异常类体系结构
Java的异常类都继承自Throwable
类,主要分为两大分支:
Throwable ├── Error (不可恢复的严重错误) └── Exception (可捕获处理的异常)├── RuntimeException (运行时异常/非受检异常)└── 其他Exception (受检异常)
二、异常分类
1. Error(错误)
-
特点:严重系统错误,应用程序通常无法处理
-
示例:
-
OutOfMemoryError
:内存耗尽 -
StackOverflowError
:栈溢出 -
VirtualMachineError
:JVM故障
-
2. Exception(异常)
(1) 受检异常(Checked Exception)
-
特点:
-
必须被捕获或声明抛出
-
编译时检查
-
-
常见异常:
-
IOException
:I/O操作失败 -
SQLException
:数据库访问错误 -
ClassNotFoundException
:类未找到 -
FileNotFoundException
:文件未找到
-
(2) 非受检异常(Unchecked Exception/RuntimeException)
-
特点:
-
不强制捕获或声明
-
通常由程序逻辑错误引起
-
-
常见异常:
-
NullPointerException
:空指针引用 -
ArrayIndexOutOfBoundsException
:数组越界 -
IllegalArgumentException
:非法参数 -
ArithmeticException
:算术错误(如除零)
-
三、异常处理机制
1. try-catch-finally块
try {// 可能抛出异常的代码FileInputStream fis = new FileInputStream("test.txt");
} catch (FileNotFoundException e) {// 处理特定异常System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {// 处理更一般的异常System.out.println("IO错误: " + e.getMessage());
} finally {// 无论是否发生异常都会执行System.out.println("执行清理工作");
}
2. throws声明
public void readFile() throws FileNotFoundException, IOException {// 方法可能抛出异常,由调用者处理FileInputStream fis = new FileInputStream("test.txt");// ...
}
3. throw主动抛出异常
public void setAge(int age) {if (age < 0) {throw new IllegalArgumentException("年龄不能为负数");}this.age = age;
}
四、自定义异常
// 自定义受检异常
public class InsufficientFundsException extends Exception {private double amount;public InsufficientFundsException(double amount) {super("资金不足,缺少: " + amount);this.amount = amount;}public double getAmount() {return amount;}
}// 自定义非受检异常
public class InvalidInputException extends RuntimeException {public InvalidInputException(String message) {super(message);}
}
五、异常处理最佳实践
-
具体优先原则:先捕获具体异常,再捕获一般异常
-
不要忽略异常:空的catch块是糟糕的做法
-
合理使用finally:释放资源等清理工作
-
避免过度使用受检异常:考虑是否真的需要调用者处理
-
异常信息要丰富:包含足够的问题描述
-
考虑异常转换:将底层异常转换为业务异常
try {// 业务代码
} catch (SQLException e) {// 将技术异常转换为业务异常throw new BusinessException("数据库操作失败", e);
}
六、Java 7增强的异常处理
1. try-with-resources
try (FileInputStream fis = new FileInputStream("test.txt");BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {// 自动资源管理String line = br.readLine();// ...
} catch (IOException e) {e.printStackTrace();
}
// 无需finally块关闭资源
2. 多重捕获
try {// 可能抛出多种异常的代码
} catch (IOException | SQLException e) {// 统一处理多种异常System.out.println("发生异常: " + e.getClass().getName());
}
七、异常性能考虑
-
异常创建开销大:异常对象包含栈轨迹信息
-
不要用异常控制流程:异常处理应只用于异常情况
-
预检查优于异常捕获:如检查null而非捕获NullPointerException
八、常见异常处理模式
1. 重试模式
int retries = 3;
while (retries > 0) {try {// 可能失败的操作operation();break;} catch (Exception e) {retries--;if (retries == 0) {throw e;}Thread.sleep(1000); // 等待后重试}
}
2. 异常转换
public void serviceMethod() throws ServiceException {try {// 调用DAOdao.accessDatabase();} catch (SQLException e) {// 转换为业务异常throw new ServiceException("数据库访问失败", e);}
}
九、总结
Java异常处理的关键点:
-
理解异常类层次结构和分类
-
掌握try-catch-finally基本处理机制
-
合理使用throws和throw
-
遵循异常处理最佳实践
-
必要时创建自定义异常
-
利用Java 7+的增强特性