当前位置: 首页 > news >正文

深入理解 Java 异常处理机制

目录

1. 异常体系结构

2. 异常分类

2.1 Error(错误)

2.2 Exception(异常)

2.2.1 受检异常(Checked Exception)

2.2.2 非受检异常(Unchecked Exception)

3. 异常处理机制

3.1 try-catch-finally 块

3.2 try-with-resources(Java 7+)

3.3 多重catch块

4. 抛出异常

4.1 throw 关键字

4.2 throws 关键字

5. 自定义异常

6. 异常处理最佳实践

6.1 不要忽略异常

6.2 使用有意义的异常信息

6.3 异常链(Exception Chaining)

7. 常见的异常处理模式

7.1 重试机制

7.2 防御性编程

8. 总结

关键要点:


异常处理是 Java 编程中至关重要的部分,它帮助我们编写更健壮、更可靠的程序。本文将全面介绍 Java 异常处理的各个方面。

1. 异常体系结构

Java 的异常类都继承自 Throwable 类,主要分为两大体系:

Throwable├── Error (错误)│     ├── OutOfMemoryError│     ├── StackOverflowError│     └── VirtualMachineError│└── Exception (异常)├── RuntimeException (运行时异常/非受检异常)│     ├── NullPointerException│     ├── ArrayIndexOutOfBoundsException│     ├── IllegalArgumentException│     └── ArithmeticException│└── 其他Exception (受检异常)├── IOException├── SQLException├── FileNotFoundException└── ClassNotFoundException

2. 异常分类

2.1 Error(错误)

表示严重的系统级错误,程序通常无法处理这些错误。

public class ErrorExample {public static void main(String[] args) {// StackOverflowErrorrecursiveMethod(0);// OutOfMemoryError// List<Object> list = new ArrayList<>();// while (true) {//     list.add(new Object());// }}private static void recursiveMethod(int i) {System.out.println(i);recursiveMethod(i + 1); // 导致栈溢出}
}

2.2 Exception(异常)

程序可以处理的异常情况,分为受检异常和非受检异常。

2.2.1 受检异常(Checked Exception)

编译器要求必须处理的异常。

public class CheckedExceptionExample {public void readFile() {try {FileReader file = new FileReader("nonexistent.txt");BufferedReader reader = new BufferedReader(file);String line = reader.readLine();System.out.println(line);reader.close();} catch (FileNotFoundException e) {System.out.println("文件未找到: " + e.getMessage());} catch (IOException e) {System.out.println("IO错误: " + e.getMessage());}}// 或者抛出异常public void readFile2() throws IOException {FileReader file = new FileReader("nonexistent.txt");BufferedReader reader = new BufferedReader(file);String line = reader.readLine();System.out.println(line);reader.close();}
}
2.2.2 非受检异常(Unchecked Exception)

编译器不要求强制处理的异常,通常是编程错误。

public class UncheckedExceptionExample {public void example() {// NullPointerExceptionString str = null;// System.out.println(str.length()); // 抛出NPE// ArrayIndexOutOfBoundsExceptionint[] arr = new int[5];// System.out.println(arr[10]); // 抛出AI0OBE// ArithmeticExceptionint a = 10;int b = 0;// System.out.println(a / b); // 抛出AE// IllegalArgumentExceptionsetAge(-5); // 可能抛出IAE}public void setAge(int age) {if (age < 0) {throw new IllegalArgumentException("年龄不能为负数: " + age);}// 设置年龄逻辑}
}

3. 异常处理机制

3.1 try-catch-finally 块

public class ExceptionHandling {public void processFile(String filename) {FileReader reader = null;try {reader = new FileReader(filename);// 读取文件内容int data = reader.read();while (data != -1) {System.out.print((char) data);data = reader.read();}} catch (FileNotFoundException e) {System.err.println("文件不存在: " + e.getMessage());} catch (IOException e) {System.err.println("读取文件时发生IO错误: " + e.getMessage());} finally {// 无论是否发生异常都会执行try {if (reader != null) {reader.close();}} catch (IOException e) {System.err.println("关闭文件时发生错误: " + e.getMessage());}}}
}

3.2 try-with-resources(Java 7+)

自动资源管理,简化资源关闭操作。

public class TryWithResourcesExample {public void readFile(String filename) {try (FileReader reader = new FileReader(filename);BufferedReader bufferedReader = new BufferedReader(reader)) {String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}} catch (FileNotFoundException e) {System.err.println("文件未找到: " + e.getMessage());} catch (IOException e) {System.err.println("IO错误: " + e.getMessage());}// 资源会自动关闭,无需finally块}
}

3.3 多重catch块

public class MultiCatchExample {public void processInput(String input) {try {int number = Integer.parseInt(input);System.out.println("数字: " + number);} catch (NumberFormatException e) {System.err.println("输入不是有效的数字: " + input);} catch (Exception e) {System.err.println("发生未知错误: " + e.getMessage());} finally {System.out.println("处理完成");}}// Java 7+ 多重异常捕获public void processData(String data) {try {// 可能抛出多种异常的操作parseAndValidate(data);} catch (NumberFormatException | IllegalArgumentException e) {System.err.println("数据格式错误: " + e.getMessage());} catch (IOException e) {System.err.println("IO错误: " + e.getMessage());}}
}

4. 抛出异常

4.1 throw 关键字

public class ThrowExample {public void withdraw(double amount) {if (amount <= 0) {throw new IllegalArgumentException("取款金额必须大于0");}if (amount > balance) {throw new InsufficientFundsException("余额不足", amount, balance);}balance -= amount;}private double balance = 1000;
}// 自定义异常
class InsufficientFundsException extends RuntimeException {private final double requestedAmount;private final double availableBalance;public InsufficientFundsException(String message, double requestedAmount, double availableBalance) {super(message);this.requestedAmount = requestedAmount;this.availableBalance = availableBalance;}public double getRequestedAmount() {return requestedAmount;}public double getAvailableBalance() {return availableBalance;}
}

4.2 throws 关键字

public class ThrowsExample {// 声明可能抛出的受检异常public void readConfigFile() throws IOException, FileNotFoundException {Properties props = new Properties();try (InputStream input = new FileInputStream("config.properties")) {props.load(input);}}// 调用者必须处理这些异常public void loadConfiguration() {try {readConfigFile();} catch (IOException e) {System.err.println("无法读取配置文件: " + e.getMessage());// 使用默认配置loadDefaultConfig();}}private void loadDefaultConfig() {// 加载默认配置}
}

5. 自定义异常

// 受检异常
public class DatabaseException extends Exception {private final String sqlState;private final int errorCode;public DatabaseException(String message, String sqlState, int errorCode) {super(message);this.sqlState = sqlState;this.errorCode = errorCode;}public DatabaseException(String message, String sqlState, int errorCode, Throwable cause) {super(message, cause);this.sqlState = sqlState;this.errorCode = errorCode;}public String getSqlState() {return sqlState;}public int getErrorCode() {return errorCode;}@Overridepublic String toString() {return String.format("DatabaseException[sqlState=%s, errorCode=%d]: %s", sqlState, errorCode, getMessage());}
}// 非受检异常
public class BusinessException extends RuntimeException {private final String errorCode;private final Map<String, Object> details;public BusinessException(String errorCode, String message) {super(message);this.errorCode = errorCode;this.details = new HashMap<>();}public BusinessException(String errorCode, String message, Map<String, Object> details) {super(message);this.errorCode = errorCode;this.details = details != null ? new HashMap<>(details) : new HashMap<>();}public String getErrorCode() {return errorCode;}public Map<String, Object> getDetails() {return Collections.unmodifiableMap(details);}public void addDetail(String key, Object value) {details.put(key, value);}
}

6. 异常处理最佳实践

6.1 不要忽略异常

public class BestPractices {// 错误的做法:忽略异常public void badPractice() {try {// 可能抛出异常的操作processData();} catch (Exception e) {// 空的catch块 - 绝对不要这样做!}}// 正确的做法:适当处理异常public void goodPractice() {try {processData();} catch (SpecificException e) {// 记录日志logger.error("处理数据时发生错误", e);// 恢复或重试retryOperation();} catch (AnotherException e) {// 转换异常类型throw new BusinessException("PROCESS_ERROR", "处理失败", e);}}
}

6.2 使用有意义的异常信息

public class MeaningfulExceptions {public void validateUser(User user) {if (user == null) {throw new IllegalArgumentException("用户对象不能为null");}if (user.getName() == null || user.getName().trim().isEmpty()) {throw new IllegalArgumentException("用户名不能为空");}if (user.getAge() < 0 || user.getAge() > 150) {throw new IllegalArgumentException("年龄必须在0-150之间: " + user.getAge());}}
}

6.3 异常链(Exception Chaining)

public class ExceptionChaining {public void processOrder(Order order) {try {validateOrder(order);calculateTotal(order);processPayment(order);} catch (ValidationException e) {throw new OrderProcessingException("订单验证失败", e);} catch (PaymentException e) {throw new OrderProcessingException("支付处理失败", e);} catch (Exception e) {throw new OrderProcessingException("处理订单时发生未知错误", e);}}
}

7. 常见的异常处理模式

7.1 重试机制

public class RetryPattern {private static final int MAX_RETRIES = 3;private static final long RETRY_DELAY = 1000; // 1秒public void executeWithRetry(Runnable operation) {int attempt = 0;while (attempt < MAX_RETRIES) {try {operation.run();return; // 成功则退出} catch (RetryableException e) {attempt++;if (attempt >= MAX_RETRIES) {throw new MaxRetriesExceededException("操作重试次数超过限制", e);}System.out.println("操作失败,第" + attempt + "次重试...");try {Thread.sleep(RETRY_DELAY);} catch (InterruptedException ie) {Thread.currentThread().interrupt();throw new OperationInterruptedException("操作被中断", ie);}}}}
}

7.2 防御性编程

public class DefensiveProgramming {public void processData(String data) {// 参数校验if (data == null) {throw new IllegalArgumentException("数据不能为null");}if (data.trim().isEmpty()) {throw new IllegalArgumentException("数据不能为空字符串");}try {// 业务逻辑doProcess(data);} catch (BusinessException e) {// 已知的业务异常handleBusinessException(e);} catch (Exception e) {// 未知异常,转换为业务异常throw new BusinessException("UNKNOWN_ERROR", "处理数据时发生未知错误", e);}}
}

8. 总结

关键要点:

  1. 了解异常体系:Error vs Exception,受检异常 vs 非受检异常
  2. 正确使用处理机制:try-catch-finally,try-with-resources
  3. 合理抛出异常:使用 throw 和 throws
  4. 创建有意义的异常:自定义异常类,提供有用的错误信息
  5. 遵循最佳实践:不要忽略异常,使用异常链,适当记录日志


文章转载自:

http://AVQFSeeG.stpkz.cn
http://73h6WwbK.stpkz.cn
http://WV3L3lfR.stpkz.cn
http://5uBe1G3N.stpkz.cn
http://HB7MVuCV.stpkz.cn
http://o9PScmcQ.stpkz.cn
http://DgrxJefK.stpkz.cn
http://uzSnEvIe.stpkz.cn
http://l3MH4iaK.stpkz.cn
http://G9BWPAxS.stpkz.cn
http://fR9bbbXM.stpkz.cn
http://v7jdOwkl.stpkz.cn
http://XIRO0dWo.stpkz.cn
http://OfpwPNNt.stpkz.cn
http://qflCDt1S.stpkz.cn
http://xsczSpYK.stpkz.cn
http://6faVNE8e.stpkz.cn
http://oFu9OCJB.stpkz.cn
http://86cUCZDs.stpkz.cn
http://pUyCE7r3.stpkz.cn
http://NZVZViKO.stpkz.cn
http://mB01lIrB.stpkz.cn
http://o8rEsYuG.stpkz.cn
http://1LK4mbmF.stpkz.cn
http://P7m2hcUN.stpkz.cn
http://f0w9F2pM.stpkz.cn
http://fOyuxKkY.stpkz.cn
http://BVSttEqX.stpkz.cn
http://MEf2ziBU.stpkz.cn
http://oSW2px3b.stpkz.cn
http://www.dtcms.com/a/383842.html

相关文章:

  • AI产品经理面试宝典第93天:Embedding技术选型与场景化应用指南
  • commons-csv
  • 【C++】类和对象1
  • MySQL学习笔记01-连接 数据模型
  • 高等教育学
  • LeetCode 1446.连续字符
  • 力扣966 元音拼写器(三个哈希表解法)详解
  • godot+c#操作sqlite并加解密
  • 利用DeepSeek实现服务器客户端模式的DuckDB原型
  • 使用Conda创建Python环境并在PyCharm中配置运行项目
  • 【项目】-Orange Pi Zero 3 编译内核测试LED
  • 【知识点讲解】Multi-Head Latent Attention (MLA) 权威指南
  • 《人性的弱点:激发他人活力》读书笔记
  • 类的封装(Encapsulation)
  • 上下文管理器和异步I/O
  • Python中的反射
  • 大模型对话系统设计:实时性与多轮一致性挑战
  • 电脑优化开机速度的5种方法
  • Vue3基础知识-Hook实现逻辑复用、代码解耦
  • 家庭宽带可用DNS收集整理和速度评测2025版
  • NumPy 模块
  • Kubernetes基础使用
  • 归并排序递归与非递归实现
  • 第9课:工作流编排与任务调度
  • 淘客app的接口性能测试:基于JMeter的高并发场景模拟与优化
  • C++ 继承:从概念到实战的全方位指南
  • Python中全局Import和局部Import的区别及应用场景对比
  • S16 赛季预告
  • 【硬件-笔试面试题-95】硬件/电子工程师,笔试面试题(知识点:RC电路中的时间常数)
  • synchronized锁升级的过程(从无锁到偏向锁,再到轻量级锁,最后到重量级锁的一个过程)