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

Java异常处理详解:掌握try-catch-finally与try-with-resources,避开空指针等踩坑点

之前跟你们聊过 Java 接口多实现、泛型这些知识点,也安利过 Cursor 编辑器,今天咱们回归 Java 基础,说说 “异常处理”—— 这玩意儿看着简单,不少人写代码时却总爱忽略,结果线上出了 bug 都不知道咋排查。小索奇之前维护一个老项目,就因为前人没处理空指针异常,用户操作时突然闪退,查日志才发现是某个对象没初始化,那排查过程别提多闹心了。

先搞懂啥是异常?简单说就是代码运行时出的 “意外”,比如你想读取一个文件,结果文件被删了;或者你想把字符串转整数,结果字符串是 “abc”,这些都会触发异常。要是不处理,程序就会直接崩溃,给用户的体验也太差了,对吧?

Java 里处理异常主要靠 try-catch-finally 这三兄弟,咱们一个个说。try 块里放可能出异常的代码,比如:

try {

// 可能出异常的代码:把字符串转整数

int num = Integer.parseInt ("abc");

}

要是 try 块里真出了异常,就会跳转到 catch 块处理,比如给用户弹个提示:

catch (NumberFormatException e) {

// 处理 “字符串转整数失败” 的异常

System.out.println ("请输入正确的数字格式!");

// 还能打印异常日志,方便排查问题

e.printStackTrace ();

}

这里要注意,catch 块要抓具体的异常,别一上来就用 Exception(所有异常的父类)。比如上面的例子,明明是 NumberFormatException,你却写 catch (Exception e),虽然也能处理,但以后排查时,你就不知道具体是哪种异常了 —— 小索奇之前就见过有人把所有异常都用 Exception 抓,出了问题光看日志都分不清是空指针还是数组越界,排查效率低得要命。

然后是 finally 块,不管 try 块里有没有异常,它都会执行。最常用的场景就是关闭资源,比如读取文件后关闭流:

try {

FileReader reader = new FileReader ("test.txt");

// 读取文件的操作

} catch (FileNotFoundException e) {

System.out.println ("文件找不到!");

} finally {

// 不管有没有异常,都关闭流

reader.close (); // 这里要注意,reader 可能没初始化,会报错

}

哎,这里又有个坑!要是 try 块里初始化 reader 时就出了异常(比如文件找不到),reader 就没被创建,这时候在 finally 里调用 reader.close (),又会触发空指针异常。咋解决呢?Java 7 之后出了 try-with-resources 语法,能自动关闭资源,不用手动写 finally:

try (FileReader reader = new FileReader ("test.txt")) {

// 读取文件的操作

} catch (FileNotFoundException e) {

System.out.println ("文件找不到!");

}

看到没?只要把资源初始化放在 try 后面的括号里,程序结束后会自动关闭,再也不用操心 finally 里的关闭逻辑了。小索奇现在写文件操作、数据库连接的代码,全用 try-with-resources,省了不少代码,还避免了资源泄漏的问题。

除了系统自带的异常,咱们还能自定义异常。比如你做一个电商项目,用户余额不足时要抛异常,这时候就可以写个自定义异常:

// 自定义 “余额不足” 异常,继承 RuntimeException

class InsufficientBalanceException extends RuntimeException {

// 构造方法,传异常信息

public InsufficientBalanceException (String message) {

super (message);

}

}

用的时候直接抛就行:

public void pay (double amount) {

double balance = 100; // 假设用户余额 100

if (amount > balance) {

// 余额不足,抛自定义异常

throw new InsufficientBalanceException ("余额不足,还差" + (amount - balance) + "元!");

}

}

自定义异常要注意,尽量继承 RuntimeException(运行时异常),别继承 Exception(编译时异常)。因为编译时异常会强制你用 try-catch 处理,要是每个业务异常都得写 try-catch,代码会变得特别啰嗦;而运行时异常可以选择性处理,比如在全局异常处理器里统一处理,更灵活。小索奇做项目时,所有业务异常都是自定义的 RuntimeException,再用 Spring 的 @ControllerAdvice 写个全局处理器,不管哪抛异常,都能统一返回友好的提示,特别方便。

说到这儿可能有人会问:“那我是不是把所有代码都用 try-catch 包起来就行?” 当然不是!比如空指针异常,最好的处理方式是提前判断,而不是等它抛出来再抓。比如:

// 不好的写法:等空指针异常再处理

try {

String name = user.getName ();

} catch (NullPointerException e) {

e.printStackTrace ();

}

// 好的写法:提前判断 user 是不是 null

if (user != null) {

String name = user.getName ();

} else {

System.out.println ("用户对象不能为空!");

}

异常处理的核心是 “预防为主,处理为辅”,能提前避免的异常就别等它发生,对吧?

你们平时写代码时,有没有因为没处理异常踩过坑?比如程序突然崩溃,或者日志里全是模糊的 Exception 信息?可以在评论区跟小索奇聊聊,咱们一起把异常处理这块儿的细节抠得更细~

搜索即兴小索奇,点击关注,加入社区群聊,获取更多好用工具和资源

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

相关文章:

  • 20250901的学习笔记
  • 全栈智算系列直播回顾 | 智算中心对网络的需求与应对策略(下)
  • 【LeetCode】3670. 没有公共位的整数最大乘积 (SOSDP)
  • 笔记:人工神经网络
  • Vue基础知识-Vue中:class与:style动态绑定样式
  • DiffusionGPT-LLM驱动的文本生成图像系统
  • OpenStack网络类型解析
  • Markdown 语法全面指南
  • EXPLAIN 和 EXPLAIN ANALYZE
  • 【AI报表】JimuReport 积木报表 v2.1.3 版本发布,免费可视化报表和大屏
  • Python 爬虫案例:爬取豆瓣电影 Top250 数据
  • 【开题答辩全过程】以 基于SSM的高校疫情防控管理系统为例,包含答辩的问题和答案
  • docker中的命令(六)
  • 轻量实现 OCPP 1.6 JSON 协议(欧洲版)的充电桩调试平台
  • AI使用指南:9月开学季,自动生成教学PPT
  • C++ 用于运行时类型识别的typeinfo库使用指南
  • 飞致云开源社区月度动态报告(2025年8月)
  • 苍穹外卖项目实战(日记十三)-记录实战教程及问题的解决方法-(day3-5) 修改菜品功能实现
  • C# FlaUI win 自动化框架,介绍
  • 用只能以关键字指定和只能按位置传入的参数来设计清晰的接口(Effective Python 第25条)
  • 利用 DrissionPage 精准获取淘宝商品描述:Python 爬虫实战指南
  • shell之扩展
  • 奇瑞QQ的后轮制动器设计cad+三维图+设计说明书
  • 【Java】谈谈IdentityHashMap
  • 前阿里专家揭秘:你对中国十大GEO专家的认知,99%都是错的
  • 苹果ipa应用安装包ios系统闪退问题
  • 携程旅行网景区,评论数据爬虫项目数据库保存附源码
  • 需求工程——你真的懂吗
  • C 基础(1) - 初识C语言
  • 在Docker容器中运行Windows:Dockur Windows项目全面解析