刚接触 Java 时,很多人会把“报错”“异常”“Error”混在一起看,结果要么一股脑全部 try-catch,要么看到异常就不知道该不该处理。其实,Java 的异常机制有一套很清晰的层次:哪些属于程序运行中的可处理问题,哪些是编译阶段就不能忽略的风险,哪些又是 JVM 层面的严重故障。
这篇文章按“先理解概念,再看分类,最后看体系和处理边界”的顺序来梳理。看完后,你至少能判断三件事:异常到底是什么、常见异常分别属于哪一类,以及面对 Error 和 Exception 时,处理思路为什么完全不同。
什么是 Java 异常
实际开发里,理想输入和理想环境并不常见。用户输入可能不符合预期,程序要读取的文件可能不存在,数据库查询结果可能为空,程序运行过程中还可能遇到网络连接失败、内存不足、硬盘写满等情况。
这类发生在程序运行期间、会影响正常执行流程的问题,在 Java 里统称为异常,英文是 Exception。它的重点不只是“出错了”,而是程序需要对这些意外情况做出处理,避免直接崩溃。
换句话说,异常机制解决的是这样一个问题:当程序遇到非预期情况时,如何把问题明确地抛出来,并交给合适的位置处理。
先分清三类:检查性异常、运行时异常和 Error
理解 Java 异常处理,第一步不是记类名,而是先把三种常见类型分开。

检查性异常
检查性异常通常代表程序运行时可能出现、而且编写代码时不能随便忽略的问题。典型场景是打开一个并不存在的文件,这类问题往往和外部条件、用户操作或资源状态有关。
这类异常的特点是:编译阶段就会要求你面对它,不能简单跳过。
运行时异常
运行时异常通常和程序逻辑本身有关,很多情况下本来是可以通过更严谨的代码避免的。它们在编译时可以被忽略,但程序一旦跑到对应路径,仍然会在运行阶段抛出。
常见理解方式是:这类异常不一定要求你强制捕获,但它们往往暴露的是代码设计、边界判断或数据校验上的问题。
Error
Error 不是通常意义上让业务代码去处理的“异常情况”,而是更偏向 JVM 或运行环境层面的严重问题。比如栈溢出、内存耗尽,都属于程序很难靠正常业务逻辑恢复的场景。
这也是为什么很多教程会强调:Error 不是日常编码里重点捕获和恢复的对象。
Java 异常体系是怎样组织的
Java 把异常当作对象处理,所有这类问题的顶层父类都是 java.lang.Throwable。在这个基类下面,主要分成两条分支:

- Error
- Exception
这个层次关系很关键,因为它决定了一个问题到底属于“程序可以处理的运行问题”,还是“程序外部或底层环境导致的严重故障”。
从学习路径上看,先记住这条主线就够了:Throwable 是总根,下面分 Error 和 Exception,实际开发的异常处理重点通常放在 Exception 分支。
Error 和 Exception 到底有什么区别
先看 Error
Error 类对象通常由 Java 虚拟机生成并抛出,绝大多数和业务代码本身的处理流程没有直接关系。比如:
- VirtualMachineError:JVM 运行层面的错误
- OutOfMemoryError:JVM 没有足够内存继续执行
- NoClassDefFoundError:类定义相关问题
- LinkageError:链接阶段相关错误
这类问题出现时,JVM 往往会终止当前线程,程序通常也不具备可靠的恢复能力。因此,它们常被视为不可查、不可控或不适合依赖常规业务逻辑恢复的问题。
再看 Exception
Exception 分支表示的是程序运行中更常见、也更值得开发者关注和处理的问题。在这条分支下面,RuntimeException 是一个非常重要的子类。
文中提到的典型运行时异常包括:
- ArrayIndexOutOfBoundsException:数组下标越界
- NullPointerException:空指针异常
- ArithmeticException:算术异常
- MissingResourceException:丢失资源
- ClassNotFoundException:找不到类
这类异常通常被归到“不检查异常”的理解范围中,程序可以选择捕获,也可以不捕获。但从编码实践看,它们大多不是“环境不可控”,而是提醒你代码里可能存在空值处理不足、边界检查缺失、资源准备不完整等问题。
所以,面对 RuntimeException,更重要的往往不是“怎么包一层 try-catch”,而是为什么会发生,以及能不能从逻辑上提前避免。
新手写异常处理时,应该先建立什么判断
如果你刚开始学 Java,可以先用一个简单标准来判断:
- 遇到 Exception,优先思考“这个问题是否应该被程序感知、记录或处理”
- 遇到 RuntimeException,进一步追问“是不是代码逻辑本身就写得不够严谨”
- 遇到 Error,通常不要把它当成普通业务异常去设计恢复流程
这也是为什么异常处理不是“见异常就捕获”这么简单。捕获只是手段,分类和判断才是前提。只有先分清异常处在哪个分支、问题是不是可恢复,后面的处理方式才不会跑偏。
总结:先看体系,再谈捕获
理解 Java 异常体系,是学会异常处理的基础。你至少要先分清三件事:检查性异常强调“不能忽略”,运行时异常强调“很多本可避免”,而 Error 则更多表示 JVM 或运行环境层面的严重故障。
把 Throwable → Error / Exception 这条主线理顺之后,再去学习 try-catch、throws、finally 等具体写法会更容易,也更不容易陷入“所有异常都靠捕获解决”的误区。









