Java 实战 -Error和Exception有什么区别?


网罗开发 (小红书、快手、视频号同名)

大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员

👋 大家好,我是展菲!

📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。

📣 公众号"Swift社区",每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。

💬 微信端添加好友"fzhanfei",与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。

📅 最新动态:2025 年 3 月 17 日

快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!

文章目录

前言

最近在代码审查的时候,发现团队里有些小伙伴对 Error 和 Exception 的概念有点混淆。有人把所有的异常都叫 Exception,也有人把系统错误叫 Error,但具体什么时候用哪个,好像也不是很清楚。

其实这个问题在很多编程语言中都存在,比如 Java、Python、Swift 等。虽然不同语言的具体实现可能不太一样,但 Error 和 Exception 的本质区别是相通的。今天我们就来聊聊 Error 和 Exception 到底有什么区别,以及在实际开发中应该如何正确使用它们。

Error 和 Exception 的基本概念

在开始之前,我们先来理解一下这两个概念的基本含义。

**Error(错误)**通常指的是系统级的错误,这些错误往往是程序无法恢复的,或者恢复起来非常困难。比如内存溢出、栈溢出、系统资源耗尽等。这些错误一般不是由程序逻辑问题引起的,而是由系统环境、硬件资源等外部因素导致的。

**Exception(异常)**则是指程序运行过程中出现的异常情况,这些异常通常是可以被程序捕获和处理的。比如数组越界、空指针引用、文件不存在、网络连接失败等。这些异常往往是由程序的设计问题、逻辑错误或者外部输入导致的。

简单来说,Error 是"系统说不行",Exception 是"程序说有问题"。

两者的核心区别

虽然 Error 和 Exception 都是程序运行时的异常情况,但它们有几个关键的区别:

严重程度不同

Error 通常比 Exception 更严重。Error 往往意味着系统级别的故障,比如内存溢出(OutOfMemoryError)、栈溢出(StackOverflowError)等。这些错误一旦发生,程序通常无法继续正常运行,甚至可能导致整个应用崩溃。

Exception 相对来说就没那么严重了。虽然有些 Exception 也会导致程序崩溃(比如未捕获的运行时异常),但大多数 Exception 都是可以被程序捕获和处理的。比如文件读取失败,我们可以提示用户重新选择文件;网络请求失败,我们可以重试或者显示错误信息。

处理方式不同

对于 Error,我们通常不应该尝试捕获和处理。因为 Error 往往意味着系统资源已经耗尽或者系统环境出现了严重问题,这时候程序已经无法正常工作了,强行处理可能会让问题变得更糟。

对于 Exception,我们应该主动捕获和处理。这是程序健壮性的重要体现。比如在读取文件时,我们应该捕获 IOException,然后给用户一个友好的提示,而不是让程序直接崩溃。

来源不同

Error 通常来自系统层面,比如 JVM 运行时错误、操作系统错误等。这些错误不是由我们的业务代码直接引起的,而是由底层系统或环境问题导致的。

Exception 通常来自应用层面,比如我们的业务逻辑、API 调用、数据处理等。这些异常往往可以通过改进代码逻辑、添加校验、重试机制等方式来处理。

实际应用场景

让我们通过几个实际的场景来理解 Error 和 Exception 的区别:

场景一:内存溢出

假设你正在开发一个图片处理应用,用户上传了一张非常大的图片。如果你的程序试图将整个图片加载到内存中,而系统内存不足,就会抛出 OutOfMemoryError。

这是一个典型的 Error。因为内存不足是系统资源问题,不是你的程序逻辑问题。虽然你可以通过优化代码(比如分块处理图片)来避免这个问题,但一旦内存真的耗尽了,程序就很难恢复了。

正确的做法是:在程序设计阶段就考虑内存限制,避免一次性加载过大的数据。如果真的遇到了 OutOfMemoryError,最好的处理方式可能是记录错误日志,然后优雅地退出程序,而不是试图捕获和处理这个错误。

场景二:文件读取失败

假设你的应用需要读取一个配置文件。如果文件不存在,或者文件被其他程序占用,就会抛出 FileNotFoundException 或 IOException。

这是一个典型的 Exception。因为文件读取失败是可以通过程序逻辑来处理的。你可以捕获这个异常,然后给用户一个友好的提示,比如"配置文件不存在,请检查文件路径",或者使用默认配置。

java 复制代码
try {
    File configFile = new File("config.properties");
    // 读取配置文件
} catch (FileNotFoundException e) {
    // 文件不存在,使用默认配置
    logger.warn("配置文件不存在,使用默认配置");
    loadDefaultConfig();
} catch (IOException e) {
    // 文件读取失败,提示用户
    logger.error("读取配置文件失败", e);
    showErrorDialog("无法读取配置文件,请检查文件权限");
}

场景三:网络请求超时

假设你的应用需要调用一个远程 API。如果网络连接不稳定,或者服务器响应慢,可能会抛出 SocketTimeoutException 或 ConnectException。

这也是一个典型的 Exception。你可以捕获这个异常,然后实现重试机制,或者给用户一个友好的提示。

java 复制代码
int maxRetries = 3;
for (int i = 0; i < maxRetries; i++) {
    try {
        // 发送网络请求
        return httpClient.execute(request);
    } catch (SocketTimeoutException e) {
        if (i == maxRetries - 1) {
            // 最后一次重试也失败了
            throw new ApiException("网络请求超时,请检查网络连接");
        }
        // 等待一段时间后重试
        Thread.sleep(1000 * (i + 1));
    }
}

场景四:空指针引用

假设你的代码中有一个对象可能为 null,但你没有做空值检查就直接使用了它,就会抛出 NullPointerException。

这也是一个典型的 Exception。虽然 NullPointerException 是运行时异常,不需要强制捕获,但我们应该在代码中主动避免这种情况。

java 复制代码
// 不好的做法
String name = user.getName(); // 如果 user 为 null,会抛出 NullPointerException
System.out.println(name.length());

// 好的做法
if (user != null) {
    String name = user.getName();
    if (name != null) {
        System.out.println(name.length());
    }
}

不同语言中的实现

虽然 Error 和 Exception 的概念是相通的,但不同语言的实现方式可能不太一样:

Java 中,Error 和 Exception 都是 Throwable 的子类。Error 包括 OutOfMemoryError、StackOverflowError 等系统级错误;Exception 包括 RuntimeException(运行时异常)和 CheckedException(检查异常)。

Python 中,所有的异常都继承自 BaseException。系统退出异常(SystemExit、KeyboardInterrupt)类似于 Error,其他异常类似于 Exception。

Swift 中,Error 是一个协议,任何遵循 Error 协议的类型都可以被抛出。Swift 没有严格区分 Error 和 Exception,但我们可以通过命名和文档来区分系统级错误和应用级异常。

最佳实践

在实际开发中,我们应该遵循以下原则:

对于 Error(系统级错误):

  1. 不要尝试捕获和处理系统级错误
  2. 在程序设计阶段就考虑资源限制,避免触发系统错误
  3. 如果真的遇到了系统错误,记录日志并优雅退出

对于 Exception(应用级异常):

  1. 主动捕获和处理可能出现的异常
  2. 给用户提供友好的错误提示
  3. 实现重试机制、降级方案等容错处理
  4. 记录详细的异常日志,方便问题排查

代码设计建议:

  1. 使用防御性编程,提前检查可能的问题
  2. 合理使用异常处理,不要过度捕获异常
  3. 区分可恢复的异常和不可恢复的异常
  4. 对于关键操作,实现重试和降级机制

总结

Error 和 Exception 虽然都是程序运行时的异常情况,但它们有本质的区别:

  • Error 是系统级的错误,通常无法恢复,不应该被捕获处理
  • Exception 是应用级的异常,可以被捕获和处理,是程序健壮性的重要体现

在实际开发中,我们应该:

  • 通过合理的设计避免系统级错误
  • 主动捕获和处理应用级异常
  • 给用户提供友好的错误提示
  • 实现完善的容错和降级机制

理解 Error 和 Exception 的区别,不仅能帮助我们写出更健壮的代码,还能让我们在面对问题时更快地定位和解决。

相关推荐
枫斗.2 小时前
Spring AI 自定义 ChatClient Bean 注入冲突问题详解
java·人工智能·spring
郝学胜-神的一滴2 小时前
Python中的with语句与try语句:资源管理的两种哲学
linux·服务器·开发语言·python·程序人生·算法
是三好2 小时前
javaSE
java·后端·spring
曹轲恒2 小时前
SpringBoot整合SpringMVC(下)
java·spring boot·spring
季明洵2 小时前
备考蓝桥杯第四天
java·数据结构·算法·leetcode·链表·哈希算法
空空kkk2 小时前
spring boot——配置文件
java·数据库·spring boot
what丶k2 小时前
Spring Boot 3 注解大全(附实战用法)
java·spring boot·后端
gAlAxy...2 小时前
Thymeleaf 从入门到精通:Spring Boot 模板引擎实战指南
java·spring boot·后端
焦糖玛奇朵婷2 小时前
就医陪诊小程序|从软件开发视角看实用度✨
java·大数据·jvm·算法·小程序