异常是什么
就是程序运行的时候出了意外状况,比如你去ATM取钱,余额不足——这就是一个”异常”
Java不会让程序直接崩掉,而是把这个意外包装成一个对象,你可以接住它、处理它
所有异常相关的类都在 java.lang 包下,不用额外import
Throwable 层次结构
Java异常体系就像一棵家族树,顶端是 Throwable,下面分两大分支
1 | Throwable(所有异常的祖宗) |
Error 和 Exception 的区别
Error 是 JVM 层面的灾难,程序员处理不了,出现了基本就是要崩
Exception 是程序层面的问题,程序员可以写代码来应对
受检异常 vs 非受检异常
这是异常体系里最核心的区分,面试必问
受检异常(Checked Exception)
编译器强制你处理,你不处理就编译不过
就像出门前老妈逼你带伞——“天气预报说要下雨,你不带伞别想出门”
典型代表:IOException、SQLException、FileNotFoundException
处理方式:要么 try-catch 捕获,要么 throws 甩给调用者
非受检异常(Unchecked Exception / RuntimeException)
编译器不管,但运行时可能炸
就像你走路可能摔跤——没人能提前阻止你,但你可以注意脚下
典型代表:NullPointerException、ArrayIndexOutOfBoundsException
通常是程序员写了bug,应该从代码层面避免,而不是 try-catch
| 对比项 | 受检异常 Checked | 非受检异常 Unchecked |
|---|---|---|
| 继承关系 | 继承 Exception(不含RuntimeException) |
继承 RuntimeException |
| 编译器是否强制处理 | 强制,不处理编译报错 | 不强制,编译能过 |
| 出现时机 | 通常是外部环境问题(文件、网络、数据库) | 通常是代码逻辑问题(空指针、越界) |
| 处理方式 | try-catch 或 throws |
修复代码逻辑,必要时才 catch |
| 典型代表 | IOException、SQLException |
NullPointerException、ClassCastException |
| 设计理念 | “这个问题可能会发生,你必须提前准备” | “这个问题是你代码写错了,去改代码” |
常见异常对照表
| 异常名 | 什么情况下出现 | 怎么避免 |
|---|---|---|
NullPointerException |
对null对象调用方法或访问属性 | 使用前先判null,或用Optional |
ArrayIndexOutOfBoundsException |
数组下标超出范围(< 0 或 >= length) | 循环条件写对,i < arr.length |
ClassCastException |
强制类型转换失败,比如把Dog转成Cat | 转换前用 instanceof 判断 |
ArithmeticException |
整数除以0 | 除法前检查除数是否为0 |
NumberFormatException |
字符串转数字失败,比如 Integer.parseInt("abc") |
转换前校验字符串格式 |
StringIndexOutOfBoundsException |
字符串下标越界 | 检查下标范围 |
StackOverflowError |
递归没有正确退出条件,无限递归 | 确保递归有终止条件 |
OutOfMemoryError |
创建了太多对象,内存不够 | 检查内存泄漏,调整JVM参数 |
IOException |
文件读写、网络通信出错 | try-catch处理,检查文件是否存在 |
FileNotFoundException |
要读的文件不存在 | 先用 File.exists() 判断 |
ConcurrentModificationException |
遍历集合时修改了集合 | 用Iterator的remove,或用CopyOnWriteArrayList |
代码示例:异常的基本演示
1 |
|
常见坑
坑1:catch了Exception就觉得万事大吉
不要无脑 catch (Exception e) {},空catch块会吞掉异常,出了问题你都不知道
至少打个日志:e.printStackTrace() 或者用日志框架记录
坑2:把Error也catch了
catch (Throwable t) 会连Error一起接住,但Error你根本处理不了
正确做法:只catch你能处理的异常
坑3:用异常来控制流程
别写 try { ... } catch (Exception e) { ... } 来代替 if-else 判断
异常是用来处理意外情况的,不是用来做正常逻辑控制的,性能也差
练习题
题1:看代码说输出
1 | public static void main(String[] args) { |
题2:以下哪些是受检异常?
A. NullPointerException → 非受检(RuntimeException子类)
B. IOException → 受检
C. ArrayIndexOutOfBoundsException → 非受检(RuntimeException子类)
D. SQLException → 受检
E. ClassCastException → 非受检(RuntimeException子类)
答案:B和D
题3:Error和Exception的区别是什么?分别举例
Error:JVM级别的严重错误,程序无法处理。如 OutOfMemoryError、StackOverflowError
Exception:程序级别的异常,可以通过代码处理。如 IOException、NullPointerException
相关笔记
try-catch-finally | throw与throws | 自定义异常
| 上一章 | 目录 | 下一章 |
|---|---|---|
| 泛型 | java基础 | try-catch-finally |