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

Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)

Java从入门到“放弃”(精通)之旅🚀——JavaSE终篇(异常)

在这里插入图片描述

一、异常的概念与体系结构

在这里插入图片描述

1.1 什么是异常?

在生活中,当一个人表情痛苦时,我们可能会关心地问:"你是不是生病了?"在程序中也是如此,即使我们绞尽脑汁将代码写得尽善尽美,程序运行时仍可能出现各种问题,比如数据格式不对、网络不通畅、内存不足等。

在Java中,将程序执行过程中发生的不正常行为称为异常。例如:

// 算术异常
System.out.println(10 / 0);  // ArithmeticException: / by zero// 数组越界异常
int[] arr = {1, 2, 3};
System.out.println(arr[100]);  // ArrayIndexOutOfBoundsException// 空指针异常
int[] arr = null;
System.out.println(arr.length);  // NullPointerException

1.2 异常的体系结构

Java中的异常种类繁多,为了分类管理,Java维护了一个异常体系结构:
在这里插入图片描述

Throwable
├── Error
└── Exception├── IOException├── ClassNotFoundException├── CloneNotSupportedException└── RuntimeException├── ArithmeticException├── NullPointerException├── ArrayIndexOutOfBoundsException└── ...
  • Throwable:异常体系的顶层类
  • Error:Java虚拟机无法解决的严重问题,如StackOverflowError和OutOfMemoryError
  • Exception:程序员可以通过代码处理的异常

1.3 异常的分类

根据发生时机,异常可分为:

  1. 编译时异常(Checked Exception):在编译期间就能发现的异常
  2. 运行时异常(Unchecked Exception):RuntimeException及其子类,在程序运行时才会出现
// 编译时异常示例
@Override
public Person clone() {return (Person)super.clone();  // 需要处理CloneNotSupportedException
}// 运行时异常示例
int[] arr = null;
System.out.println(arr.length);  // NullPointerException

二、异常的处理方式

2.1 防御式编程的两种风格

  1. LBYL(Look Before You Leap):事前检查
boolean ret = false;
ret = 登陆游戏();
if (!ret) {处理登陆游戏错误;return;
}
ret = 开始匹配();
if (!ret) {处理匹配错误;return;
}
// ...更多检查
  1. EAFP(It’s Easier to Ask Forgiveness than Permission):事后处理
try {登陆游戏();开始匹配();游戏确认();选择英雄();载入游戏画面();
} catch (登陆游戏异常) {处理登陆游戏异常;
} catch (开始匹配异常) {处理开始匹配异常;
}
// ...更多catch块

Java主要采用EAFP风格,通过五个关键字处理异常:throwtrycatchfinallythrows

2.2 异常的抛出(throw)

使用throw关键字抛出异常:

public static int getElement(int[] array, int index) {if (null == array) {throw new NullPointerException("传递的数据为null");}if (index < 0 || index >= array.length) {throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");}return array[index];
}public static void main(String[] args) {int[] array = {1, 2, 3};getElement(array, 3);  // 抛出ArrayIndexOutOfBoundsException
}

2.3 异常的捕获

2.3.1 异常声明(throws)
public class Config {public void openConfig(String filename) throws FileNotFoundException {if (!filename.equals("config.ini")) {throw new FileNotFoundException("配置文件名字不对");}// 打开文件}
}public static void main(String[] args) throws FileNotFoundException {Config config = new Config();config.openConfig("config.ini");
}
2.3.2 try-catch捕获处理
public static void main(String[] args) {Config config = new Config();try {config.openConfig("config.txt");System.out.println("文件打开成功");} catch (FileNotFoundException e) {System.out.println("文件不存在,错误信息:" + e.getMessage());e.printStackTrace();  // 打印完整调用栈}System.out.println("异常处理后的代码");
}
2.3.3 finally块
public static int getData() {Scanner sc = null;try {sc = new Scanner(System.in);int data = sc.nextInt();return data;} catch (InputMismatchException e) {e.printStackTrace();} finally {System.out.println("finally中代码");if (null != sc) {sc.close();  // 确保资源被释放}}return 0;
}

面试题:finally中的语句一定会执行吗?
答:正常情况下一定会执行,除非遇到:

  1. 在try或catch块中调用System.exit()
  2. 程序所在线程死亡
  3. 关闭CPU

三、异常处理流程

public static void main(String[] args) {try {func();} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}System.out.println("after try catch");
}public static void func() {int[] arr = {1, 2, 3};System.out.println(arr[100]);  // 抛出异常
}

异常处理流程总结:

  1. 执行try中的代码
  2. 出现异常则匹配catch块
  3. 找到匹配则执行catch,否则向上传递
  4. 无论是否匹配,finally都会执行
  5. 如果一直未被处理,最终由JVM处理,程序终止

四、自定义异常类

Java内置异常类不能满足所有需求时,可以自定义异常:

// 自定义用户名异常
class UserNameException extends Exception {public UserNameException(String message) {super(message);}
}// 自定义密码异常
class PasswordException extends Exception {public PasswordException(String message) {super(message);}
}// 使用自定义异常
public class Login {private String userName = "admin";private String password = "123456";public static void loginInfo(String userName, String password) throws UserNameException, PasswordException {if (!userName.equals("admin")) {throw new UserNameException("用户名错误!");}if (!password.equals("123456")) {throw new PasswordException("密码错误!");}System.out.println("登陆成功");}public static void main(String[] args) {try {loginInfo("admin", "123");} catch (UserNameException e) {System.out.println("用户名异常:" + e.getMessage());} catch (PasswordException e) {System.out.println("密码异常:" + e.getMessage());}}
}

注意事项:

  • 自定义异常通常会继承自 Exception 或者 RuntimeException
  • 继承自 Exception 的异常默认是受查异常
  • 继承自 RuntimeException 的异常默认是非受查异常.

总结

Java异常处理是编写健壮程序的关键技术。通过合理的异常处理,我们可以:

  1. 提高程序的容错性
  2. 分离正常逻辑和错误处理逻辑
  3. 提供更清晰的错误信息
  4. 确保资源被正确释放

记住异常处理的原则:对可恢复情况使用受检异常,对编程错误使用运行时异常,避免滥用异常处理机制。

在这里插入图片描述


在这里插入图片描述
JavaSE往期专栏

  • Java从入门到“放弃”(精通)之旅——启航①
  • Java从入门到“放弃”(精通)之旅——数据类型与变量②
  • Java从入门到“放弃”(精通)之旅——运算符③
  • Java从入门到“放弃”(精通)之旅——程序逻辑控制④
  • Java从入门到“放弃”(精通)之旅——方法的使用⑤
  • Java从入门到“放弃”(精通)之旅——数组的定义与使用⑥
  • Java从入门到“放弃”(精通)之旅——类和对象全面解析⑦
  • Java从入门到“放弃”(精通)之旅——继承与多态⑧
  • Java从入门到“放弃”(精通)之旅——抽象类和接口⑨
  • Java从入门到“放弃”(精通)之旅——String类⑩
    在这里插入图片描述
http://www.xdnf.cn/news/130681.html

相关文章:

  • 畅游Diffusion数字人(28):InstantID原班人马提出个性化人物定制InstantCharacter
  • [AI Workflow] 基于多语种知识库的 Dify Workflow 构建与优化实践
  • 【产品经理】常见的交互说明撰写方法
  • leetcode刷题日记——逆波兰表达式求值
  • R7周:糖尿病预测模型优化探索
  • 佐航BYQ2321直阻变比二合一全面升级!
  • RunnerGo API性能测试实战与高并发调优
  • Python图形界面编程(二)
  • 使用 Frp 同时实现 HTTP 和 HTTPS 内网穿透
  • SQLMesh 表格对比指南:深入理解 table_diff 工具的实际应用
  • c++进阶——类与继承
  • 命令行指引的尝试
  • 【Linux学习笔记】进程的fork创建 exit终止 wait等待
  • 如何让 HTML 文件嵌入另一个 HTML 文件:详解与实践
  • Java面试高频问题(26-28)
  • 使用浏览器的Clipboard API实现前端复制copy功能
  • 基准指数选股策略思路
  • 风光储能+智能调度,这才是企业未来能源管理的最优解
  • Linux进程学习【基本认知】
  • vscode切换Python环境
  • C++中的浅拷贝和深拷贝
  • 【现代深度学习技术】循环神经网络06:循环神经网络的简洁实现
  • 头歌实训之索引
  • MySQL 库的操作 -- 增删改查,备份和恢复,系统编码
  • 深度解析之算法之分治(快排)
  • Python-36:饭馆菜品选择问题
  • 使用jsrsasign进行RSA加密解密
  • Vue 2 和 Vue 3 的详细对比,从 生命周期、API、响应式系统、函数调用 等多角度展开,最后附表格总结
  • 【C到Java的深度跃迁:从指针到对象,从过程到生态】第三模块·面向对象深度进化 —— 第十二章 接口:比C函数指针更强大的契约
  • 数学基础 -- 欧拉公式的推导过程学习