很多人分不清!Java 运行时异常和编译时异常的真正区别

原文来自于:zha-ge.cn/java/18

很多人分不清!Java 运行时异常和编译时异常的真正区别

深夜的一次"翻车"

那是一个月黑风高的夜晚(好吧,其实就是普通的周五加班),我正在为公司的订单系统写一个文件上传功能。代码写得飞起,心情美滋滋,准备提交代码回家吃宵夜。

然而,当我满怀信心地点击运行按钮时...

java 复制代码
Exception in thread "main" java.io.FileNotFoundException: upload/orders.txt (系统找不到指定的路径。)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at OrderUploader.processFile(OrderUploader.java:23)

什么?!我明明写的代码在IDE里没有任何红色波浪线啊!为什么运行时突然冒出个异常?

这就是我第一次真正意识到 编译时异常 和 运行时异常 区别的时刻。

两兄弟的身世之谜

Java的异常家族就像两兄弟:

异常类型 别名 检查时机 是否强制处理
编译时异常 Checked Exception 编译期 必须处理
运行时异常 Unchecked Exception 运行期 可选处理

编译时异常就像那个严格的哥哥,在你写代码时就会跳出来说:"兄弟,这里可能出问题,你必须想好怎么处理!"

运行时异常则像调皮的弟弟,编译时乖乖的,运行时突然给你来个"惊喜"。

踩坑瞬间:文件操作的"温柔陷阱"

回到我那个翻车的夜晚。我写的代码是这样的:

java 复制代码
public void uploadOrderFile(String fileName) throws IOException {
    FileInputStream fis = new FileInputStream(fileName);
    // 处理文件内容...
    fis.close();
}

IDE为什么没有报错?因为我已经在方法签名上声明了throws IOException!这是编译时异常的经典处理方式。

但问题来了:当我在调用这个方法的地方忘记处理异常时...

java 复制代码
// 这样写IDE会报红!必须处理IOException
orderUploader.uploadOrderFile("orders.txt"); 

这时候IDE才会提醒你:老兄,你调用的方法可能抛出编译时异常,必须处理!

转折:运行时异常的"隐身术"

相比之下,运行时异常就"狡猾"多了。比如最常见的空指针异常:

java 复制代码
List<String> orderList = getOrderList(); // 可能返回null
// 下面这行编译完全正常,但运行时可能爆炸
orderList.add("新订单"); // NullPointerException等着你呢

IDE不会给你任何警告,代码编译得好好的,结果运行时突然:

arduino 复制代码
Exception in thread "main" java.lang.NullPointerException

这就是运行时异常的特点:编译器不管,全靠程序员自觉!

经验启示:如何优雅应对两兄弟

经过无数次踩坑后,我总结出了这样的经验:

编译时异常的处理策略

  • 文件IO、网络连接、数据库操作 → 大概率是编译时异常
  • 必须用 try-catch 或者 throws 声明
  • 适合处理"预料之中"的异常情况

运行时异常的防范策略

  • 空指针、数组越界、类型转换 → 典型的运行时异常
  • 通过代码逻辑预防(null检查、边界校验)
  • 适合处理"编程错误"

最佳实践

  1. 编译时异常:该处理就处理,别一味往上抛
  2. 运行时异常:提前预防胜过事后处理
  3. 自定义异常:根据业务需求选择继承RuntimeException还是Exception

醒悟时刻

现在回想起那个加班的夜晚,我才明白:

  • 编译时异常像个严格的老师,强制你思考异常处理
  • 运行时异常像个隐藏的地雷,全靠经验和习惯来规避

掌握了这两者的区别,写代码时就能做到:该严格时严格,该灵活时灵活。毕竟,异常处理不是为了应付编译器,而是为了让程序更健壮,让自己少加班!

现在的我,再也不会在深夜被突如其来的异常吓到了。因为我知道,每一个异常都有它的"脾气",掌握了它们的性格,就能和它们和谐相处。

你呢?还在被这两兄弟搞得晕头转向吗?

相关推荐
Wang's Blog4 分钟前
Java 项目实战: 交友项目 - MongoDB 入门:体系结构和命令行操作
java·mongodb·交友
小溪学编程5 分钟前
将 Bean 放入 Spring 容器中的方式有哪些?
java·后端·spring
java_nnnn9 分钟前
LeetCode刷题滑动窗口(水果成篮+找到字符串中所有字母的异位词)Java
java·开发语言·leetcode
用户37215742613511 分钟前
Java 读取、修改和清空 PDF 文档属性(元数据)
java
SL_staff14 分钟前
从‘改一行代码等三天’到‘改完即生效’:实施工程师的逻辑引擎避坑手记
java·产品·全栈
小羊没烦恼!18 分钟前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
hhwyqwqhhwy19 分钟前
设备树之 provider 和 consumer
java·linux·前端
\光辉岁月/22 分钟前
9.日期时间类
java·date·localdatetime·日期类
用户37215742613526 分钟前
Java 操作 PPT 超链接:添加、修改和删除
java
需要8261 小时前
容器化 Java:镜像瘦身与 JVM 容器感知(cgroup)
java·开发语言·jvm