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

Java异常:认识异常、异常的作用、自定义异常

目录

    • 1.什么是异常?
      • 1)运行时异常
      • 2)编译时异常
    • 2.异常的作用
      • 1)Java 异常在定位 BUG 中的核心作用
      • 2)Java 异常作为方法内部特殊返回值的作用
      • 3)自定义异常

1.什么是异常?

在这里插入图片描述
Error:代表的系统级别错误(属于严重问题)
Exception:异常,代表的才是我们程序可能出现的问题,通常会用Exception以及它的子类来封装程序出现的问题
运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如:数组索引越界异常),通常因为编写的代码有问题导致
编译时异常:编译阶段就会出现错误提醒的(如:日期解析异常),通常是Java官方对认为容易出问题的地方进行异常提醒,需要抛出异常或捕获异常,对异常进行处理

1)运行时异常

int[] arr = {1,2,3};
System.out.println(arr[3]);
执行后报数组越界异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3at excepttion.Test.main(Test.java:6)System.out.println(10/0);
执行后报运算异常:
Exception in thread "main" java.lang.ArithmeticException: / by zeroat excepttion.Test.main(Test.java:5)String s = null;
System.out.println(s.length());
执行后报空指针异常:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "s" is nullat excepttion.Test.main(Test.java:6)

2)编译时异常

在这里插入图片描述
案例:处理异常可在方法名后使用throws关键字将异常抛给方法调用者处理或使用try…catch捕获并抛出异常

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class Test {public static void main(String[] args) {String str = "2025-05-06";//存在编译异常的方法调用时需使用try-catch块处理异常或在main方法中使用throws关键字try {StringToDate(str); //调用方法转换字符串为日期} catch (ParseException e) { //当字符串内容的格式不符合要求时(yyyy-MM-dd),会抛出ParseException异常e.printStackTrace(); //打印异常信息}}//定义转换字符串为日期的方法并使用throws关键字抛出异常给调用者处理public static void StringToDate(String str) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//调用parse方法将字符串转换成日期对象//此处出现编译异常的原因:输入的字符串格式和可能和SimpleDateFormat的格式不一致//例如需要输入2019/09/09,但SimpleDateFormat的格式是yyyy-MM-dd//因此此处会抛出ParseException,解决方式:使用try...catch或者throws关键字Date date = sdf.parse(str);System.out.println(date);}
}

案例:存在多个编译时异常可使用Exception接所有类型的异常

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class Test2 {public static void main(String[] args) {//使用try-catch块处理异常try {StringToDate();} catch (Exception e) {e.printStackTrace();}}//使用Exception接收所有异常public static void StringToDate() throws Exception {String str = "2025-05-06";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//出现ParseException异常Date date = sdf.parse(str);System.out.println(date);//创建读取文件对象,抛出FileNotFoundException异常FileReader fr = new FileReader("d:/a.txt");}
}

2.异常的作用

Java 异常的作用分析:定位 BUG 与作为方法内部特殊返回值

1)Java 异常在定位 BUG 中的核心作用

Java 异常机制的核心价值之一是提供精准的错误定位能力,其通过异常堆栈跟踪(Stack Trace)实现对程序运行时错误的可视化追踪。当程序抛出未捕获的异常时,JVM 会自动生成包含异常类型、发生位置及调用链路的堆栈信息,帮助开发者快速定位问题根源。
①异常堆栈跟踪的信息构成
异常堆栈跟踪是定位 BUG 的 “导航图”,其结构包含三部分关键信息:
异常类型与消息:首行显示异常的全限定类名(如java.lang.NullPointerException)及异常消息(如Cannot invoke “String.length()” because “s” is null),直接揭示错误类别及触发原因;
堆栈帧序列:后续每行对应一个栈帧(StackTraceElement),包含异常传播路径中的调用信息,具体格式为at 类名.方法名(文件名:行号),其中行号是定位具体代码位置的关键。

例如,执行以下代码时:

public class Bug定位示例 {public static void main(String[] args) {String str = null;printLength(str); // 第4行:调用printLength方法}private static void printLength(String s) {System.out.println(s.length()); // 第8行:尝试调用null对象的length()方法}
}

会抛出NullPointerException,其堆栈跟踪信息如下:

java.lang.NullPointerException: Cannot invoke "String.length()" because "s" is nullat Bug定位示例.printLength(Bug定位示例.java:8)  // 异常发生点:第8行at Bug定位示例.main(Bug定位示例.java:4)        // 调用链路:main方法第4行触发

②基于堆栈跟踪的 BUG 定位流程

开发者可通过以下步骤定位 BUG:

识别异常类型:通过异常类名判断错误类别(如NullPointerException表示空指针访问,IndexOutOfBoundsException表示数组越界),缩小排查范围;
解析异常消息:异常消息通常包含直接原因(如上述示例中s is null),可快速定位变量状态异常;
追踪堆栈帧链路:堆栈帧从下到上为调用链(最下方是异常发生点,上方是调用方),结合行号直接定位到具体代码行(如示例中的第 8 行s.length()),进而检查变量赋值、方法参数传递等上下文逻辑,最终找到根本原因(如 main 方法中str被赋值为null)。

③实战价值:减少 “盲猜式” 调试

传统调试依赖日志打印或断点调试,需手动排查代码执行路径;而异常堆栈跟踪直接标记错误发生的精确位置及传播路径,避免开发者在海量代码中 “盲猜”。例如,在多层调用的复杂系统中(如 Controller→Service→DAO),异常堆栈可直接显示异常是在 DAO 层 SQL 执行时抛出,还是在 Service 层参数校验时触发,大幅缩短定位时间。

2)Java 异常作为方法内部特殊返回值的作用

在方法设计中,除返回正常值外,常需传递 “特殊状态”(如文件不存在、参数非法、业务规则冲突等)。传统方案(如返回null、错误码)存在信息缺失或易被忽略的问题,而 Java 异常可作为结构化的 “特殊返回值”,高效传递异常状态并强制处理。

①传统特殊状态返回方案的局限性
错误码方案:如返回-1表示 “参数错误”、-2表示 “资源不存在”,需开发者主动检查返回值,若遗漏(如直接使用返回值参与运算),会导致错误传播。例如:

// 错误码方案示例(存在隐患)
public int divide(int a, int b) {if (b == 0) return -1; // 返回-1表示除数为0return a / b;
}
// 调用方可能忘记检查错误码,直接使用返回值:
int result = divide(5, 0);
System.out.println(result); // 输出-1,错误被掩盖

null返回方案:用null表示 “无结果”(如查询不到数据),但调用方若未判空直接操作(如调用null对象的方法),会触发NullPointerException,反而引入新错误。

②异常作为特殊返回值的优势

强制关注特殊状态:

受检异常(Checked Exception):如IOException、ClassNotFoundException,编译器强制要求调用方通过try-catch捕获或throws声明抛出,避免遗漏处理。例如,FileInputStream构造方法抛出FileNotFoundException(受检异常),强制开发者处理 “文件不存在” 的场景:

// 受检异常强制处理示例
public void readFile(String path) {try (FileInputStream fis = new FileInputStream(path)) { // 此处必须处理FileNotFoundException// 文件读取逻辑} catch (FileNotFoundException e) {System.err.println("文件不存在:" + path); // 显式处理特殊状态} catch (IOException e) {System.err.println("文件读取失败:" + e.getMessage());}
}

非受检异常(Unchecked Exception):如NullPointerException、IllegalArgumentException,虽不强制捕获,但通过异常类型和消息提醒开发者关注(如参数校验失败),比null或错误码更直观。

3)自定义异常

异常可封装比错误码 /null更详细的信息,包括:
异常类型:通过不同异常类区分特殊状态类别(如IllegalArgumentException表示参数错误,TimeoutException表示超时);
异常消息:自定义文本描述具体原因(如"用户ID=123不存在");
自定义字段:通过自定义异常类添加业务相关属性(如错误码、用户 ID、操作类型等)。
例如,自定义业务异常传递多维度信息:

// 自定义异常作为特殊返回值(携带业务上下文)
class UserNotFoundException extends Exception {private final int userId; // 携带异常相关的用户IDprivate final String errorCode; // 携带业务错误码public UserNotFoundException(String message, int userId, String errorCode) {super(message);this.userId = userId;this.errorCode = errorCode;}// Getter方法获取自定义字段public int getUserId() { return userId; }public String getErrorCode() { return errorCode; }
}// 方法中抛出自定义异常
public User getUserById(int id) throws UserNotFoundException {User user = userDao.query(id);if (user == null) {// 抛出异常时传递详细信息:消息、用户ID、错误码throw new UserNotFoundException("用户不存在", id, "USER_NOT_FOUND_001");}return user;
}// 调用方捕获异常并获取上下文
try {User user = getUserById(123); 
} catch (UserNotFoundException e) {log.error("查询失败:{},用户ID:{},错误码:{}", e.getMessage(), e.getUserId(), e.getErrorCode()); // 输出:查询失败:用户不存在,用户ID:123,错误码:USER_NOT_FOUND_001
}

(3)中断错误流程,避免错误扩散

当方法遇到无法处理的特殊状态时,抛出异常可立即中断当前执行流程,阻止错误结果继续传播。例如,支付系统中若检测到 “余额不足”,抛出InsufficientBalanceException可终止后续扣款逻辑,避免资金异常。

三、总结
Java 异常机制在程序开发中具有双重核心价值:
定位 BUG:通过堆栈跟踪提供异常发生的精确位置(类、方法、行号)及调用链路,是高效调试的 “导航系统”;

作为特殊返回值:相比错误码 /null,异常通过强制处理机制(受检异常)、丰富上下文信息(类型、消息、自定义字段)及流程中断能力,更可靠地传递方法执行中的特殊状态,提升代码健壮性与可维护性。
合理使用异常机制,可显著降低调试成本,减少因特殊状态处理不当导致的系统故障。

http://www.dtcms.com/a/322976.html

相关文章:

  • ChatGPT 5的编程能力宣传言过其实
  • 97-基于Python的大众点评数据分析预测系统
  • 七、《Serverless架构:按毫秒计费的成本革命》--从新浪AI推理平台50%效能提升看无服务器本质
  • 数据结构——优先级队列(PriorityQueue):一文解决 Top K 问题!
  • 可视化大屏 SDK 数据结构设计:从拖拽组件到最终渲染的全链路
  • 2025-08-09 李沐深度学习13——经典卷积神经网络 (1)
  • 嵌入式知识日常问题记录及用法总结(一)
  • C++2024 年一级
  • Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
  • buuctf:inndy_echo、actf_2019_babystack
  • 花生4CL基因家族鉴定及对干旱与盐胁迫响应分析--文献精读157
  • 【AI论文】种子扩散模型:一种具备高速推理能力的大规模扩散语言模型
  • 智慧农业-无人机视角庄稼倒伏农作物倒伏识别分割数据集labelme格式541张1类别
  • C语言指针完全指南:从入门到精通
  • Selenium使用超全指南
  • OpenCV图像裁剪与 ROI 操作
  • 全志刷机工具:PhoenixSuit-全志芯片处理器-刷机工具安装包及最详细使用教程指南
  • Python day39
  • Web3: 用ERC-1400革新公司股权激励
  • 【原创】基于 Flask 的简单文件收集器
  • 【33】C#实战篇——点击按钮弹出指定路径对话框,选择指定类型文件;;;文件过滤器显示指定的一种文件,几种类型文件 同时显示
  • Pytest中实现自动生成测试用例脚本代码
  • 扩散LLM推理新范式:打破生成长度限制,实现动态自适应调节
  • 在ubuntu服务器下安装cuda和cudnn(笔记)
  • ImageJ 实用技巧:通过 Overlay 实现图像透明标记的完整教程
  • NTP /Chrony 网络时间协议
  • 当配置项只支持传入数字,即无法指定单位为rem,需要rem转px
  • 本地连接跳板机
  • 【Windows】成批复制某个特定的文件
  • 《算法导论》第 13 章 - 红黑树