Java 异常处理全解析:从基础到自定义异常的实战指南
Java 异常处理全解析:从基础到自定义异常的实战指南
一、Java 异常体系:Error 与 Exception 的本质区别
1. 异常体系核心架构
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable
作为所有异常的超类。
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Erro
r和异常Exception
。
Java 异常体系基于Throwable
类,分为两大分支:
Throwable
├─ Error(错误)
│ └─ 例:OutOfMemoryError、StackOverflowError
└─ Exception(异常)├─ Checked Exception(编译时异常)│ └─ 例:IOException、SQLException└─ Unchecked Exception(运行时异常)└─ 例:NullPointerException、ArrayIndexOutOfBoundsException
2.什么是异常以及异常的简单分类
- 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
- 异常发生在程序运行期间,它影响了正常的程序执行流程。
要理解java异常处理是如何工作的,你需要掌握以下三种类型的异常Exception
:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误
Error
: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
3. Error vs Exception
Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
维度 | Error | Exception |
---|---|---|
本质 | JVM 底层错误,不可恢复 | 程序运行中的异常情况 |
处理方式 | 无法捕获,需重启 JVM | 可捕获处理或声明抛出 |
典型场景 | 内存溢出、类加载失败 | 空指针、数组越界、用户输入错误 |
4. Checked vs Unchecked 异常
-
Checked 异常:
- 必须显式处理(捕获或声明抛出)
- 示例:文件读取时的
FileNotFoundException
try {FileReader reader = new FileReader("file.txt"); } catch (FileNotFoundException e) {e.printStackTrace(); }
-
Unchecked 异常:
- 无需强制处理(运行时检查)
- 示例:参数校验失败的
IllegalArgumentException
public void checkAge(int age) {if (age < 0) {throw new IllegalArgumentException("年龄不能为负数");} }
二、异常处理核心机制:捕获与抛出
1. 异常捕获语法(try-catch-finally)
try {// 可能抛出异常的代码int result = 10 / 0; // 抛出ArithmeticException
} catch (ArithmeticException e) { // 捕获具体异常System.out.println("错误原因:" + e.getMessage()); // 输出:/ by zeroe.printStackTrace(); // 打印堆栈跟踪信息
} catch (Exception e) { // 父类异常捕获(需放在最后)// 通用异常处理
} finally {// 可选:无论是否异常都会执行(常用于资源释放)System.out.println("执行finally块");
}
2. 异常抛出关键字
throw(方法内抛出异常实例)
public static int divide(int a, int b) {if (b == 0) {throw new ArithmeticException("除数不能为0"); // 主动抛出异常}return a / b;
}
throws(方法声明抛出异常)
public static void readFile(String path) throws FileNotFoundException {FileReader reader = new FileReader(path); // 声明抛出Checked异常
}
3. 异常处理顺序原则
- 子类异常优先:具体异常(如
FileNotFoundException
)需写在父类异常(如IOException
)之前 - finally 的绝对性:即使 try 块中有
return
,finally 仍会执行(但返回值会被缓存)
4.本节狂神说笔记
package com.exception;public class Test {public static void main(String[] args) {int a = 10;int b = 0;//假设要捕获多个异常: 从小到大!try {//try监控区域System.out.println(a/b);} catch (Error e) {//catch(想要捕获的异常类型!)捕获异常System.out.println("Error");} catch (Exception e) {System.out.println("Exception");} catch (Throwable e) {System.out.println("Throwable");} finally {//处理善后工作System.out.println("finally");}finally 可以不要finally, 假设I0,资源,关闭!}public void a(){b();}public void b(){a();}
}
package com.exception;public class Test2 {public static void main(String[] args) {int a = 1;int b = 0;//Ctrl Alt + Ttry {System.out.println(a/b);} catch (Exception e) {e.printStackTrace();//打印错误的栈信息} finally {}}
}
package com.exception;public class Test1 {public static void main(String[] args) {try {new Test1().test(1,0);} catch (ArithmeticException e) {e.printStackTrace();}}//假设这个方法中,处理不了这个异常。方法上抛出异常public void test(int a,int b) throws ArithmeticException{if(b == 0){//throw throwsthrow new ArithmeticException();//主动的抛出异常,一般在方法中使用}}
}
三、自定义异常:打造业务专属错误体系
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
1. 自定义异常类步骤
- 创建自定义异常类。
- 在方法中通过throw关键字抛出异常对象。
- 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
步骤 1:继承 Exception 或 RuntimeException
// Checked异常(需显式处理)
public class UserAgeException extends Exception {public UserAgeException(String message) {super(message); // 调用父类构造器}
}// Unchecked异常(运行时异常)
public class InvalidInputException extends RuntimeException {public InvalidInputException(String message) {super(message);}
}
步骤 2:在业务逻辑中抛出
public void validateUser(int age) throws UserAgeException {if (age < 18) {throw new UserAgeException("用户年龄必须≥18岁"); // 抛出自定义Checked异常}
}
2. 异常处理最佳实践
(1)异常信息规范
- 包含足够上下文:
"用户ID为" + userId + "的账户不存在"
- 避免裸露捕获
Exception
:应捕获具体异常类型
(2)资源释放最佳实践
// JDK 7+ 自动资源管理(替代finally)
try (FileReader reader = new FileReader("file.txt")) {// 自动关闭资源(无需显式finally)
} catch (IOException e) {// 处理文件读取异常
}
(3)异常链使用
try {// 业务逻辑
} catch (ServiceException e) {throw new ControllerException("接口调用失败", e); // 包装异常链
}
3.实际应用中的经验总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上 try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单地调用 printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
四、常见异常处理错误与解决方案
1. 空指针异常(NPE)
错误示例:
String str = null;
int length = str.length(); // 抛出NullPointerException
解决方案:
if (str != null) {int length = str.length();
} else {throw new IllegalArgumentException("字符串不可为null");
}
2. 未处理 Checked 异常
错误示例:
public void readFile() {FileReader reader = new FileReader("file.txt"); // 编译错误:未处理IOException
}
解决方案:
// 方案1:捕获处理
try { /* ... */ } catch (IOException e) { /* ... */ }// 方案2:声明抛出
public void readFile() throws IOException { /* ... */ }
3. finally 中的 return 陷阱
错误示例:
public static int testFinally() {try {return 1;} finally {return 2; // 最终返回2,覆盖try中的return}
}
正确做法:
public static int testFinally() {int result = 1;try {return result;} finally {result = 2; // 不建议在finally中使用return}
}
五、高频面试题解析
1. Error 和 Exception 的根本区别?
- Error 是 JVM 内部错误(如内存溢出),无法通过代码处理,必须重启应用
- Exception 是程序运行中的异常,分为 Checked(编译时检查)和 Unchecked(运行时异常)
2. throw 和 throws 的区别?
关键字 | 作用 | 使用位置 | 参数类型 |
---|---|---|---|
throw | 抛出异常实例 | 方法体内部 | 异常对象 |
throws | 声明方法可能抛出的异常类型 | 方法签名 | 异常类列表 |
3. finally 块一定会执行吗?
- 正常情况下一定会执行(包括 return 前执行)
- 唯一例外:JVM 提前终止(如
System.exit(0)
)
4. 自定义异常应该继承哪个类?
- 业务需要编译时检查:继承
Exception
- 运行时异常(如参数校验失败):继承
RuntimeException
六、异常处理核心原则
- 具体捕获:优先捕获具体异常,避免使用宽泛的
Exception
- 快速失败:在方法入口校验参数,尽早抛出异常
- 信息完整:异常信息需包含定位问题的关键数据(如用户 ID、时间戳)
- 资源管理:使用
try-with-resources
自动释放 IO、数据库连接等资源
七、总结:构建健壮的异常处理体系
通过合理运用 Java 异常处理机制,开发者可以:
- 清晰区分系统错误与业务异常
- 通过捕获特定异常实现精准的错误处理
- 利用自定义异常提升业务代码的可读性
该继承哪个类?
- 业务需要编译时检查:继承
Exception
- 运行时异常(如参数校验失败):继承
RuntimeException
六、异常处理核心原则
- 具体捕获:优先捕获具体异常,避免使用宽泛的
Exception
- 快速失败:在方法入口校验参数,尽早抛出异常
- 信息完整:异常信息需包含定位问题的关键数据(如用户 ID、时间戳)
- 资源管理:使用
try-with-resources
自动释放 IO、数据库连接等资源
七、总结:构建健壮的异常处理体系
通过合理运用 Java 异常处理机制,开发者可以:
- 清晰区分系统错误与业务异常
- 通过捕获特定异常实现精准的错误处理
- 利用自定义异常提升业务代码的可读性
- 结合 finally 和 try-with-resources 确保资源安全释放
相关文章:

Java 异常处理全解析:从基础到自定义异常的实战指南
Java 异常处理全解析:从基础到自定义异常的实战指南 一、Java 异常体系:Error 与 Exception 的本质区别 1. 异常体系核心架构 Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。 在Java API中已经定义了许…...

开源AI智能名片链动2+1模式S2B2C商城小程序源码赋能下的社交电商创业者技能跃迁与价值重构
摘要:在移动互联网深度重构商业生态的背景下,社交电商创业者面临流量成本攀升、用户粘性不足、供应链协同低效等核心痛点。本文以“开源AI智能名片链动21模式S2B2C商城小程序源码”技术体系为研究对象,通过分析其技术架构、商业逻辑及实战案例…...
线程池(六):ThreadLocal相关知识详解
线程池(六):ThreadLocal相关知识详解 线程池(六):ThreadLocal相关知识详解一、概述定义与作用应用场景 二、ThreadLocal基本使用创建ThreadLocal对象设置和获取值初始化值完整示例 三、ThreadLocal的实现原…...

WSL 中 nvidia-smi: command not found的解决办法
前言 在使用基于 Linux 的 Windows 子系统(WSL)时,当我们执行某些操作后,可能会遇到输入 nvidia-smi 命令却无法被系统识别的情况。 例如,在终端中输入nvidia-smi 后,系统返回提示 -bash: nvidia-smi: co…...

FPGA前瞻篇-组合逻辑电路设计-多路复用器
多路选择器(MUX)简介 基本概念 多路选择器(MUX,Multiplexer)是一种多输入、单输出的组合逻辑电路。 它通过选择控制信号,在多个输入信号中选择一个连接到输出端。 可以理解为一个多路数字开关。 &…...
作为高速通道光纤传输模式怎么理解以及到底有哪些?
光纤的传输模式主要取决于光纤的结构(如纤芯直径和折射率分布),不同模式对应光波在光纤中传播的不同路径和电磁场分布。以下是光纤传输模式的主要分类及特点: 1. 单模光纤(Single-Mode Fiber, SMF) 核心特点: 纤芯直径极小(通常为 8-10微米),仅允许光以单一模式(…...

【Castle-X机器人】五、物联网模块配置与调试
持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】五、物联网模块配置与调试 五、物联网模块配置与调试5.1 物联网模块调试物联网模块测试:控制物联网模块:物联网模块话题五、物联网模块配置与调试 5.1 物联网模块调试 调试前需确保Castle-x与mqtt主机服务器处于同…...
马架构的Netty、MQTT、CoAP面试之旅
标题:马架构的Netty、MQTT、CoAP面试之旅 在互联网大厂的Java求职者面试中,一位名叫马架构的资深Java架构师正接受着严格的考验。他拥有十年的Java研发经验和架构设计经验,尤其对疑难问题和线索问题等有着丰富的经历。 第一轮提问ÿ…...

20250426在ubuntu20.04.2系统上打包NanoPi NEO开发板的FriendlyCore系统刷机eMMC的固件
20250426在ubuntu20.04.2系统上打包NanoPi NEO开发板的FriendlyCore系统刷机eMMC的固件 2025/4/26 21:30 缘起:使用NanoPi NEO开发板,编译FriendlyCore系统,打包eMMC固件的时候报错。 1、在ubuntu14.04下git clone异常该如何处理呢ÿ…...

JAVA---字符串
ctrlN 搜索界面(idea) API和API帮助文档 API : 应用程序编程接口(换句话说,就是别人已经写好了,我们不需要再编写,直接使用即可) Java API :就是JDK中提供的各种功能…...

MacOS 10.15上能跑大语言模型吗?
MacOS 10.15上能跑大语言模型吗? 下载安装Ollama运行大语言模型引申出的问题 MacOS 10.15.7(发布于2020年9月)作为已经发布了将近5年的系统版本能够运行当今流行的大语言模型吗?这篇文章简要介绍了在MacOS 10.15上通过Ollama运行d…...

AI Agent开发第37课-DeepSeek的多模态版JanusPro-7B本地安装
开篇 搜遍Janus Pro git issues、谷哥、国内网络,教程全都是错的。因此还是决定写一本全网唯一正确的教程。 目前网上的教程包括外网的教程都是“缺斤少量”,按照那些教程操作下来不是装不起来,就是装起来只能CPU运行,或者运行起来了Janus的Web前端老是转啊转不出内容。 …...

神经网络笔记 - 感知机
一 感知机是什么 感知机(Perceptron)是一种接收输入信号并输出结果的算法。 它根据输入与权重的加权和是否超过某个阈值(threshold),来判断输出0还是1。 二.计算方式 感知机的基本公式如下: X1, X2 : …...

阿里云基于本地知识库构建RAG应用 | 架构与场景
RAG(检索增强生成,Retrieval-Augmented Generation)是一种结合了检索和生成技术的框架,旨在通过外部知识库的检索来增强大语言模型(LLM)的生成能力。 其核心架构包括两个主要部分: 检索模块&a…...

CSS简单实用的加载动画、骨架屏有效果图
效果图 .wxml <!-- 骨架屏 --> <view wx:for"{{skeleton}}" wx:key"index" class"container center" style"--w:{{item.w}}rpx;--h:{{item.h}}rpx" /> <!-- 加载 --> <view class"arco-loading center&quo…...

3:QT联合HALCON编程—海康相机SDK二次程序开发
思路: 1.定义带UI界面的主函数类 1.1在主函数中包含其它所有类头文件,进行声明和实例化;使用相机时,是用公共相机的接口在某一个具体函数中去实例化具体的海康相机对象。 1.2设计界面:连接相机,单次采集&a…...

【前后端分离项目】Vue+Springboot+MySQL
文章目录 1.安装 Node.js2.配置 Node.js 环境3.安装 Node.js 国内镜像4.创建 Vue 项目5.运行 Vue 项目6.访问 Vue 项目7.创建 Spring Boot 项目8.运行 Spring Boot 项目9.访问 Spring Boot 项目10.实现 Vue 与 Spring Boot 联动11.安装 axios12.编写请求13.调用函数请求接口14.…...

数据结构和算法(八)--2-3查找树
目录 一、平衡树 1、2-3查找树 1.1、定义 1.2、查找 1.3、插入 1.3.1、向2-结点中插入新键 1.3.2、向一棵只含有一个3-结点的树中插入新键 1.3.3、向一个父结点为2-结点的3-结点中插入新键 1.3.4、向一个父结点为3-结点的3-结点中插入新键 1.3.5、分解根结点 1.4、2…...
Java爬虫入门:从网页抓取到数据提取(正则表达式篇)
在当今信息爆炸的时代,如何从浩瀚的互联网中快速、准确地获取所需数据成为了一个重要的技能。网络爬虫技术应运而生,它允许我们自动化地访问网页并提取其中的信息。Java作为一门功能强大且拥有丰富生态的编程语言,在构建网络爬虫方面也表现出…...

Unity-Shader详解-其二
前向渲染和延迟渲染 前向渲染和延迟渲染总的来说是我们的两种主要的渲染方式。 我们在Unity的Project Settings中的Graphic界面能够找到渲染队列的设定: 我们也可以在Main Camera这里进行设置: 那这里我们首先介绍一下两种渲染(Forward R…...

深入浅出理解并应用自然语言处理(NLP)中的 Transformer 模型
1 引言 随着信息技术的飞速发展,自然语言处理(Natural Language Processing, NLP)作为人工智能领域的一个重要分支,已经取得了长足的进步。从早期基于规则的方法到如今的深度学习技术,NLP 正在以前所未有的速度改变着我…...

当自动驾驶遇上“安全驾校”:NVIDIA如何用技术给无人驾驶赋能?
自动驾驶技术的商业化落地,核心在于能否通过严苛的安全验证。国内的汽车企业其实也在做自动驾驶,但是吧,基本都在L2级别。换句话说就是在应急时刻内,还是需要人来辅助驾驶,AI驾驶只是决策层,并不能完全掌握…...
WIN11安装Ubuntu22.04双系统,驱动cuda,配置3D GS
前言:看了很多基于3D GS开发的SLAM系统都默认在Ubuntu20.04-22.04中运行,并且WIN11不太方便安装cmake等基础编译库。所以还是在Ubuntu系统中进行咱的研究吧。 step 1. WIN11安装Ubuntu双系统 首先确认系统是否为UEFI模式。 winX进行磁盘管理ÿ…...

【OSG学习笔记】Day 9: 状态集(StateSet)与渲染优化 —— 管理混合、深度测试、雾效等渲染状态
干货开始。_ 一、StateSet核心概念与作用 StateSet 是OSG(OpenSceneGraph)中管理渲染状态的核心类,用于封装 OpenGL 渲染状态(如混合、深度测试、雾效、材质、纹理、着色器等),并将这些状态应用于节点或几何体。 通过合理组织 StateSet,可实现: 渲染状态的高效复用:…...
如何解析商品详情页面
解析商品详情页面是爬虫开发中的一个重要环节。由于商品详情页面通常包含丰富的信息,如商品名称、价格、描述、图片等,因此需要仔细分析页面结构并提取所需数据。以下是一个详细的步骤指南,展示如何使用 Java 和 Jsoup 解析商品详情页面。 一…...

Operating System 实验七 Linux文件系统实验
实验目标: 使用dd命令创建磁盘镜像文件ext2.img并格式化为ext2文件系统,然后通过mount命令挂载到Linux主机文件系统。查看ext2文件系统的超级块的信息,以及数据块的数量、数据块的大小、inode个数、空闲数据块的数量等信息 在文件系统中创建文件xxxxx.txt(其中xxxxx为你的学…...
使用 IntersectionObserver 实现懒加载提升网页性能的高效方案
在当今快节奏的网络环境中,用户对于网页加载速度的要求越来越高。对于前端开发者而言,优化网页性能、减少初始加载时间成为了一项至关重要的任务。懒加载(Lazy Loading)作为一种有效的性能优化策略,能够延迟非关键资源…...
Python-Django系列—部件
部件是 Django 对 HTML 输入元素的表示。部件处理 HTML 的渲染,以及从对应于部件的 GET/POST 字典中提取数据。 内置部件生成的 HTML 使用 HTML5 语法,目标是 <!DOCTYPE html>。例如,它使用布尔属性,如 checked…...

linux中shell脚本的编程使用
linux中shell脚本的编程使用 1.shell的初步理解1.1 怎么理解shell1.2 shell命令 2.shell编程2.1 什么是shell编程2.2 C语言编程 和 shell编程的区别 3.编写和运行第一个shell脚本程序3.1 编写时需要注意以下几点:3.1.1 shell脚本没有main函数,没有头文件…...

图像畸变-径向切向畸变实时图像RTSP推流
实验环境 注意:ffmpeg进程stdin写入两张图片的时间间隔不能太长,否则mediamtx会出现对应的推流session超时退出。 实验效果 全部代码 my_util.py #进度条 import os import sys import time import shutil import logging import time from datetime i…...