首发!首发!2026年1月18日
📑作者:午后葡萄冰
🐶专栏:Java - 专栏
🚀我们终会遇到自己的忒修斯之船~
文章目录
🌟前言
一、异常的体系结构 ☃️
二、异常的分类 🚀
1.编译时异常(受检查异常,Checked Exception)⭐
2.运行时异常(非受检查异常,Unchecked Exception)⭐
三、异常的处理方式 🍪
1.异常的抛出(throw)
2.异常的声明(throws)
3.异常的捕获(try-catch)
4.finally 关键字
四、自定义异常类 😶🌫️
✨总结
🌟前言
📑Java系列:说明一下该系列是针对Java研发
🚩这个系列会持续推新的,所以关注博主🍻,在学习Java语言的路上结伴前行吧!
在 Java 程序开发中,异常是绕不开的重要知识点。无论代码编写得多么严谨,运行时都可能遇到各种意外情况 —— 比如除数为 0、数组下标越界、网络中断等,这些情况会打断程序的正常执行流程。掌握异常的处理机制,能让我们的程序更健壮、容错性更强,同时也能快速定位和解决问题。本文将从异常的基本概念出发,逐步深入讲解异常的体系结构、处理方式、执行流程,并结合实例演示自定义异常的实现,帮助大家全面掌握 Java 异常处理。
一、异常的体系结构 ☃️
Java 的异常体系以Throwable为顶层父类,其下派生两个核心子类:Error和Exception,形成了完整的异常分类体系。
(1)Error
• 表示 Java 虚拟机无法解决的严重问题,属于系统级错误
• 典型案例:StackOverflowError(递归调用过深)、OutOfMemoryError(内存泄漏)
• 特点:一旦发生,程序无法恢复,只能终止执行
(2)Exception
• 表示程序运行过程中出现的可修复异常,程序员可通过代码处理
• 特点:处理后程序可继续执行,是异常处理的核心对象
二、异常的分类 🚀
根据异常发生的时机,可将Exception分为两类:
1.编译时异常(受检查异常,Checked Exception)⭐
发生在程序编译阶段,必须显式处理,否则无法通过编译
• 常见案例:ClassNotFoundException(类未找到)、IOException(IO 操作异常)、CloneNotSupportedException(克隆不支持异常)
2.运行时异常(非受检查异常,Unchecked Exception)⭐
发生在程序运行阶段,编译时无需显式处理
• 所有RuntimeException及其子类都属于运行时异常
• 常见案例:NullPointerException(空指针异常)、ArrayIndexOutOfBoundsException(数组越界异常)、ArithmeticException(算数异常)
⚠️ 注意:编译时的语法错误(如拼写错误system.out.println)不属于异常,而是编译失败,需要修正语法后才能运行。
三、异常的处理方式 🍪
Java的异常处理主要通过 5 个关键字实现:throw、try、catch、finally、throws。
异常的处理流程:
1.程序先执行try块中的代码
2. 若try块无异常:执行finally(若有),再执行后续代码
3. 若try块有异常:
◦ 终止try块执行,匹配catch中的异常类型
◦ 找到匹配的catch:执行catch逻辑 → 执行finally → 执行后续代码
◦ 未找到匹配的catch:异常向上传递给上层调用者
异常向上传递:若上层调用者仍无匹配的处理逻辑,继续向上传递,直到main方法
若main方法也无处理逻辑:交给 JVM 处理,JVM 打印异常堆栈信息,程序终止
1.异常的抛出(throw)
当程序检测到错误时,可通过throw关键字主动抛出指定的异常对象,将错误信息告知调用者。
throw new XXXException("异常产生的原因");
注意事项:
1.throw必须写在方法体内部
2. 抛出的对象必须是Exception或其子类实例(抛出异常非错误)
3. 抛出运行时异常(RuntimeException及其子类):可不用显式处理,交给 JVM 处理
4. 抛出编译时异常:必须显式处理(捕获或通过throws声明),否则编译失败
5. 异常抛出后,其后的代码不会执行(异常点之后的代码不可达)
2.异常的声明(throws)
throws关键字用于在方法声明中列出该方法可能抛出的异常,将异常处理责任转移给调用者。
修饰符 返回值类型 方法名(参数列表) throws 异常类型1, 异常类型2...{
// 可能抛出异常的代码
}
注意事项:
1.throws必须跟在方法参数列表之后
2.声明的异常必须是Exception或其子类(抛出异常非错误)
3.方法内部抛出多个异常时,throws后可列出多个异常类型(用逗号分隔);若异常间有父子关系,直接声明父类即可
4.调用声明编译时异常的方法时,调用者必须处理该异常(要么try-catch捕获,要么throws继续抛出)
异常间有父子关系:
// FileNotFoundException是IOException的子类,声明父类即可
public void openConfig(String filename) throws IOException{
if(filename.endsWith(".ini")){
throw new IOException("文件不是.ini文件");
}
if(!filename.equals("config.ini")){
throw new FileNotFoundException("配置文件名字不对");
}
}
3.异常的捕获(try-catch)
try-catch是真正处理异常的核心结构,用于捕获并处理try块中抛出的异常。
try{
// 可能出现异常的代码
}catch(异常类型1 e){
// 处理异常类型1的逻辑
}catch(异常类型2 e){
// 处理异常类型2的逻辑
}finally{
// 可选:无论是否发生异常,都会执行的代码
}
// 异常处理后的后续代码
注意事项:
1.try块中异常发生点之后的代码不会执行
2.异常捕获遵循 “类型匹配” 原则:catch的异常类型需与抛出的异常类型一致或为其父类
3.多个catch块的顺序:子类异常在前,父类异常在后(否则子类异常的catch块永远无法执行)
4.多个异常的合并捕获:若多个异常的处理逻辑相同,可使用|合并捕获
5.通用捕获(不推荐):使用Exception捕获所有异常,会隐藏具体异常信息,不利于问题定位
多个catch块顺序:
// 正确示例:子类异常在前,父类异常在后
try {
int[] arr = null;
System.out.println(arr[100]);
} catch (NullPointerException e) { // 子类异常
System.out.println("空指针异常");
} catch (Exception e) { // 父类异常
System.out.println("其他异常");
}
多个异常的合并捕获:
catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
System.out.println("数组下标越界或空指针异常");
e.printStackTrace();
}
4.finally 关键字
finally块用于定义无论是否发生异常都必须执行的代码,通常用于资源释放(如关闭文件、网络连接、数据库连接等)。
try{
// 可能发生异常的代码
}catch(异常类型 e){
// 异常处理逻辑
}finally{
// 必须执行的代码(资源释放等)
System.out.println("finally中的代码一定会执行");
// 释放资源:关闭Scanner
if(null != sc){
sc.close();
}
}
四、自定义异常类 😶🌫️
Java 内置的异常类无法覆盖所有业务场景(如用户登录时的用户名错误、密码错误),此时需要自定义异常类来描述特定业务异常。
👇下面是一个自定义异常实现登录的例子:
Login类:
定义自定义异常类①:
定义自定义异常类②:
运行结果:
✨总结
1.异常体系:以Throwable为顶层,分为Error(不可处理)和Exception(可处理);
2. 异常分类:编译时异常(必须处理)和运行时异常(无需强制处理);
3. 处理关键字:throw(主动抛出异常)、throws(声明异常)、try-catch(捕获处理)、finally(资源释放);
4. 处理流程:异常沿调用栈向上传递,直到被捕获或 JVM 终止程序;
5. 自定义异常:继承Exception(编译时)或RuntimeException(运行时),满足特定业务需求。
我将玫瑰藏于身后,风起花落,从此鲜花赠自己,纵马踏花向自由
🌈银河系NGC 2237玫瑰星云 🌹分享给大家,这是我想要给你的宇宙级别的浪漫!!
好了以上就是今天的全部内容,感谢你的耐心阅读,我会继续努力的!
🐻❄️既然都看到这里了,那就给博主我个 一键三连 吧!!!