15.Java异常处理:从束手无策到从容应对
目录写在前面一、什么是异常1.1 异常的概念1.2 异常的体系结构1.3 异常的分类二、异常的处理方式2.1 防御式编程的两种思路2.2 抛出异常throw2.3 声明异常throws2.4 捕获异常try-catch2.5 finally无论是否异常都要执行2.6 异常的处理流程三、自定义异常类3.1 实现自定义异常3.2 注意事项四、课后练习总结写在前面相信每一位Java初学者都曾经历过这样的时刻满怀信心地写完代码点击运行结果控制台突然冒出一片刺眼的红色错误信息。程序崩溃了而你一脸茫然地看着那个陌生的异常类名不知道发生了什么更不知道该如何解决。异常是编程路上绕不开的一道坎。但换个角度看异常其实是程序在说话——它在告诉你我这里出问题了快来帮帮我。今天这篇文章我们就来系统地学习Java的异常处理机制。掌握了它你就能听懂程序在说什么并且知道该怎么回应。一、什么是异常1.1 异常的概念异常是指在程序执行过程中发生的一种特殊情况或错误状态。它打断了程序的正常执行流程需要特别处理。在日常开发中即使程序员绞尽脑汁想把代码写得尽善尽美程序运行过程中还是难免会出现各种问题。有些问题通过代码很难完全控制比如数据格式不对、网络不通畅、内存不足等。在Java中程序执行过程中发生的不正常行为被称为异常。不同类型的异常都有对应的类来描述。比如下面这些你一定见过// 算术异常 System.out.println(10 / 0); // Exception in thread main java.lang.ArithmeticException: / by zero // 数组越界异常 int[] array {1, 2, 3}; System.out.println(array[100]); // Exception in thread main java.lang.ArrayIndexOutOfBoundsException // 空指针异常 String str null; System.out.println(str.length()); // Exception in thread main java.lang.NullPointerException1.2 异常的体系结构Java内部维护了一套完善的异常体系结构对各种异常和错误进行分类管理Throwable顶层父类 ├── Error严重问题程序无法处理 │ ├── StackOverflowError │ └── OutOfMemoryError └── Exception可处理的异常 ├── RuntimeException运行时异常/非受查异常 │ ├── NullPointerException │ ├── ArrayIndexOutOfBoundsException │ └── ArithmeticException └── 其他受查异常 ├── IOException ├── SQLException └── FileNotFoundException关键理解Throwable异常体系的顶层类派生出Error和Exception两个子类ErrorJava虚拟机无法解决的严重问题比如JVM内部错误、资源耗尽等。一旦发生程序无力回天。典型代表StackOverflowError栈溢出和OutOfMemoryError内存溢出Exception程序员可以通过代码进行处理使程序继续执行。我们平时所说的异常主要指的就是Exception1.3 异常的分类根据发生时机不同异常分为两类编译时异常受查异常在程序编译期间发生的异常编译器会强制要求处理。比如public class Person implements Cloneable { private String name; Override public Person clone() { return (Person) super.clone(); // 编译报错未处理CloneNotSupportedException } }运行时异常非受查异常在程序执行期间发生的异常编译器不强制处理。比如NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException等。注意编译时出现的语法性错误不能称之为异常。比如把System.out.println写成了system.out.println这是编译错误而不是异常。二、异常的处理方式2.1 防御式编程的两种思路面对程序中不可避免的错误主要有两种处理思路LBYL事前防御型在操作之前就做充分的检查public static int getElement(int[] array, int index) { if (array null) { System.out.println(数组为null); return -1; } if (index 0 || index array.length) { System.out.println(下标越界); return -1; } return array[index]; }这种方式的缺陷是正常流程和错误处理流程的代码混在一起整体显得比较混乱。EAFP事后认错型先操作遇到问题再处理public static int getElement(int[] array, int index) { try { return array[index]; } catch (NullPointerException e) { System.out.println(数组为null); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(下标越界); } return -1; }这种方式将正常流程和错误流程分离开来代码更清晰。Java异常处理的核心思想就是EAFP。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]; }使用throw的注意事项throw必须写在方法体内部抛出的对象必须是Exception或其子类对象如果抛出的是RuntimeException或其子类可以不处理直接交给JVM如果抛出的是编译时异常必须处理否则无法通过编译异常一旦抛出其后的代码就不会执行2.3 声明异常throwsthrows关键字用于在方法声明中列出该方法可能抛出的异常将异常的处理责任转移给调用者public void readConfig(String fileName) throws FileNotFoundException { if (!fileName.equals(config.ini)) { throw new FileNotFoundException(配置文件不是config.ini); } // 读取文件的逻辑... }使用throws的注意事项throws必须跟在方法的参数列表之后声明的异常必须是Exception或其子类如果方法内部可能抛出多个异常throws后跟多个异常类型用逗号隔开如果多个异常类型有父子关系直接声明父类即可调用声明抛出异常的方法时如果该异常是编译时异常调用者必须处理或继续抛出2.4 捕获异常try-catchthrows并没有真正处理异常只是将异常上报给调用者。如果要真正处理异常需要使用try-catchpublic static void main(String[] args) { try { readConfig(other.ini); } catch (FileNotFoundException e) { // 异常的处理方式 System.out.println(e.getMessage()); // 只打印异常信息 System.out.println(e); // 打印异常类型:异常信息 e.printStackTrace(); // 打印信息最全面推荐 } // 异常被处理后这里的代码会继续执行 System.out.println(异常如果被处理了这里的代码也可以执行); }关于异常的处理方式异常种类繁多要根据不同的业务场景来决定对于比较严重的问题比如和金钱相关的场景应该让程序直接崩溃防止造成更严重后果对于不太严重的问题大多数场景可以记录错误日志并通过监控报警程序及时通知程序员对于可能会恢复的问题比如网络相关的场景可以尝试重试使用try-catch的注意事项try块内抛出异常位置之后的代码不会被执行如果抛出异常类型与catch时异常类型不匹配异常不会被成功捕获继续往外抛try中可能抛出多个不同的异常需要用多个catch来捕获如果多个异常的处理方式完全相同可以写成catch(异常类型1 | 异常类型2 e)如果异常之间具有父子关系子类异常必须在父类异常之前捕获try { System.out.println(before); System.out.println(array[100]); System.out.println(after); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(数组下标越界异常); e.printStackTrace(); } catch (NullPointerException e) { System.out.println(空指针异常); e.printStackTrace(); }2.5 finally无论是否异常都要执行有些代码不论程序是否发生异常都需要执行。比如程序中打开的资源——网络连接、数据库连接、IO流等在程序正常或异常退出时必须进行回收。finally就是用来解决这个问题的try { // 可能会发生异常的代码 } catch (异常类型 e) { // 对捕获到的异常进行处理 } finally { // 此处的语句无论是否发生异常都会被执行到 }为什么需要finally考虑这样一个场景方法中打开了输入流在方法返回之前必须关闭它。如果不用finally可能会出现资源泄漏public int getData() { Scanner scanner new Scanner(System.in); try { int num scanner.nextInt(); return num; } catch (InputMismatchException e) { e.printStackTrace(); } finally { scanner.close(); // 无论是否发生异常都会执行 System.out.println(finally中代码); } return -1; }重要特性finally中的代码一定会在方法返回之前执行。但如果finally中也有return语句它会覆盖try或catch中的return。因此不建议在finally中写return语句。2.6 异常的处理流程当代码中出现异常时会沿着调用栈向上传递程序先执行try中的代码如果try中的代码出现异常结束try中的代码查看与catch中的异常类型是否匹配如果找到匹配的异常类型执行catch中的代码如果没有找到匹配的异常类型将异常向上传递到上层调用者无论是否找到匹配的异常类型finally中的代码都会被执行如果上层调用者也没有处理异常继续向上传递一直到main方法也没有处理交给JVM处理程序异常终止三、自定义异常类Java内置的异常类虽然丰富但不能完全覆盖实际开发中的所有场景。比如实现一个用户登录功能可能需要区分用户名错误和密码错误两种异常。3.1 实现自定义异常自定义异常通常继承自Exception或RuntimeException// 自定义异常用户名错误 class UserNameException extends RuntimeException { public UserNameException(String message) { super(message); } } // 自定义异常密码错误 class PasswordException extends RuntimeException { public PasswordException(String message) { super(message); } }然后在业务代码中使用public class LoginService { private static final String USER_NAME admin; private static final String PASSWORD 123456; public static void login(String userName, String password) { if (!USER_NAME.equals(userName)) { throw new UserNameException(用户名错误); } if (!PASSWORD.equals(password)) { throw new PasswordException(密码错误); } System.out.println(登录成功); } public static void main(String[] args) { try { login(admin, 654321); } catch (UserNameException e) { e.printStackTrace(); } catch (PasswordException e) { e.printStackTrace(); } } }3.2 注意事项继承自Exception的异常默认是受查异常编译时异常必须处理继承自RuntimeException的异常默认是非受查异常运行时异常可以不处理四、课后练习题目1​ 以下哪个不是Java中的受检异常checked exceptionA. IOExceptionB. SQLExceptionC. NullPointerExceptionD. ClassNotFoundException答案​ C题目2​ 关于try-catch-finally语句以下哪个说法是正确的A. finally块总是会执行即使try块中有return语句B. 如果catch块中抛出异常finally块就不会执行C. 一个try块后面必须跟着至少一个catch块D. finally块中的return语句会覆盖try或catch块中的return语句答案​ A、D题目3​ 关于异常处理以下哪个说法是错误的A. 子类方法抛出的异常范围不能大于父类方法声明的异常范围B. 可以在catch块中捕获多个异常类型C. RuntimeException及其子类都是非受查异常D. 使用throw关键字可以手动抛出异常但不能抛出Error答案​ D总结今天我们系统地学习了Java的异常处理机制异常的概念程序执行过程中的不正常行为异常体系Throwable → Error不可处理和 Exception可处理异常分类编译时异常受查异常和运行时异常非受查异常处理方式throw抛出、throws声明、try-catch捕获、finally收尾处理流程沿调用栈向上传递直到被处理或交给JVM自定义异常继承Exception或RuntimeException异常处理不是可有可无的装饰而是高质量软件的必备能力。一个好的程序不是不出错而是在出错时能够优雅地处理给用户友好的反馈给开发者足够的信息来定位问题。掌握异常处理你的代码将更加健壮、更加专业。

相关新闻

OpenCV4学习(1-13)

OpenCV4学习(1-13)

目录 1.环境安装: 2.示例程序: 3.认识Mat容器 单通道矩阵 1. 核心判断依据 2. 完整维度信息 3. 对比多通道写法区分 双通道示例(Vec2i,2 通道 int) 三通道示例(Vec3b,3 通道 uchar&…

2026/7/13 15:50:21 阅读更多 →
革命性AI空气动力学工具XMeshGraphNet DrivAerML:NVIDIA如何用图神经网络加速汽车设计

革命性AI空气动力学工具XMeshGraphNet DrivAerML:NVIDIA如何用图神经网络加速汽车设计

革命性AI空气动力学工具XMeshGraphNet DrivAerML:NVIDIA如何用图神经网络加速汽车设计 【免费下载链接】xmgn_drivaerml_surface 项目地址: https://ai.gitcode.com/hf_mirrors/nvidia/xmgn_drivaerml_surface XMeshGraphNet-DrivAerML是一款由NVIDIA开发的…

2026/7/13 15:48:18 阅读更多 →
为什么92%的提示词工程师仍在用非结构化写法?——ChatGPT结构化提示词的5层嵌套模型与实时效果对比数据

为什么92%的提示词工程师仍在用非结构化写法?——ChatGPT结构化提示词的5层嵌套模型与实时效果对比数据

更多请点击: https://codechina.net 第一章:为什么92%的提示词工程师仍在用非结构化写法? 当提示工程从实验性实践演变为专业岗位,一个反直觉的现象持续存在:绝大多数从业者仍依赖自由文本式提示——即无字段约束、无…

2026/7/13 15:48:18 阅读更多 →

最新新闻

Iframe 全屏自适应: 从基础CSS到跨域动态高度的完整解决方案

Iframe 全屏自适应: 从基础CSS到跨域动态高度的完整解决方案

1. 基础CSS实现静态全屏布局要让iframe铺满整个屏幕,最基础的方法是使用CSS的定位和百分比布局。我们先从最简单的场景开始:当iframe嵌入的页面高度固定,且不需要动态调整时。假设我们有一个Vue组件需要嵌入第三方页面,基础HTML结…

2026/7/13 16:43:17 阅读更多 →
钓鱼渗透测试实验复现

钓鱼渗透测试实验复现

钓鱼渗透测试实验复现用途:网络安全学习分享,仅限授权环境测试一、实验环境角色系统/工具IP地址攻击机Windows 11(矛盾武器库)10.0.0.166靶机Windows 10 x6410.0.0.153攻击机:Windows 11 Penetration Suite Toolkit - …

2026/7/13 16:41:15 阅读更多 →
清华求真书院预科班有学生未通过考核的处理结果

清华求真书院预科班有学生未通过考核的处理结果

关于清华大学求真书院 2026 级预科班少数学生未通过考核一事,目前公开信息主要聚焦于院方的回应与后续改革方向,‌尚未公布具体的“清退”名单或详细的行政处理文件‌。 根据清华大学求真书院院长丘成桐的回应,针对该事件的处理与后续安排主要…

2026/7/13 16:39:14 阅读更多 →
离散数学符号表 50+ 核心符号速查:从集合论到命题逻辑的完整释义

离散数学符号表 50+ 核心符号速查:从集合论到命题逻辑的完整释义

离散数学核心符号全解:从集合论到命题逻辑的实战指南离散数学作为计算机科学的基石,其符号系统就像程序员的第二语言。第一次接触这些符号时,我完全被各种∧、∨、⊕搞得晕头转向——直到在算法课上因为误解了一个符号含义导致整个程序逻辑出…

2026/7/13 16:39:14 阅读更多 →
智能语音修复神器:VoiceFixer让受损音频重获新生

智能语音修复神器:VoiceFixer让受损音频重获新生

智能语音修复神器:VoiceFixer让受损音频重获新生 【免费下载链接】voicefixer General Speech Restoration 项目地址: https://gitcode.com/gh_mirrors/vo/voicefixer 在数字音频处理领域,语音修复技术正经历着革命性的变革。无论是历史录音的数字…

2026/7/13 16:39:14 阅读更多 →
Unity生存射击游戏开发:从AlienShooter项目掌握核心架构与优化

Unity生存射击游戏开发:从AlienShooter项目掌握核心架构与优化

1. 项目概述:为什么选择从AlienShooter开始你的Unity生存游戏之旅?如果你正在寻找一个能串联起Unity核心开发技能,又能做出一个完整、可玩、有成就感的项目,那么一个生存射击游戏(Survival Shooter)绝对是黄…

2026/7/13 16:37:11 阅读更多 →

日新闻

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾经想要调整Palwor…

2026/7/13 0:01:19 阅读更多 →
浦东旧模块回收哪家强?专业评测带你一探究竟

浦东旧模块回收哪家强?专业评测带你一探究竟

于科技迅猛飞速迭代的当下此刻, 旧模块的回收处置, 不但关联着资源的再度利用, 而且更牵扯到数据安全以及环保合规事宜。你是不是也正为那堆积得如同山峦般的旧模块而发愁? 是不是不清楚该怎样安全且高效地去处理它们? 别忧心烦恼, 就在今日, 我会以具备权威影响力的自媒体博…

2026/7/13 0:01:19 阅读更多 →
卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

1 研究背景与现存技术痛点(提出问题)基因工程、蛋白质组学、生物制药研发流程中,蛋白质分离纯化是决定下游实验成败的关键环节。当前实验室常规蛋白质分离纯化工艺存在三类难以标准化的技术瓶颈:传统离子交换、分子筛层析无特异性…

2026/7/13 0:05:20 阅读更多 →

周新闻

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨 在一个阳光明媚的上午,互联网大厂的面试官坐在桌前,准备迎接他的面试候选人——燕双非,一个以搞笑和幽默著称的程序员。第一轮提问 面试官:燕双非,作…

2026/7/13 4:38:36 阅读更多 →
车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估在智能驾驶和车联网技术快速发展的今天,车载以太网作为新一代车载网络的核心传输技术,其物理层性能直接决定了数据传输的可靠性和稳定性。1000BASE-T1作为当前主流的…

2026/7/13 4:38:38 阅读更多 →
VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战指南嵌入式开发领域正经历一场工具链的静默革命。当传统Keil用户首次打开VSCode的扩展市场搜索EIDE时,往往会惊讶于这个看似简单的插件竟能重构十余年的开发习惯。本文将揭示如何用五个精准步骤&#xff0…

2026/7/13 4:38:40 阅读更多 →

月新闻