第6篇:Java异常有哪几种
📌系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第5篇:装箱和拆箱 |
➡️ 下一篇:第7篇:Java面向对象简介
一、核心知识点
- 异常体系分类:检查型异常(Checked Exception)、运行时异常(Runtime Exception)、错误(Error)
- 异常处理关键字:
try、catch、finally、throws、throw - 常见异常类:
NullPointerException、ArrayIndexOutOfBoundsException、IOException、SQLException等 - 异常处理规范和最佳实践
二、通俗讲解(1分钟开心学)
1. 异常是什么?
程序运行时会遇到各种意外情况,比如:
- 用户输入的年龄是-5岁(不合理)
- 要读取的文件不存在
- 网络突然断开
- 数组下标越界
这些意外就是“异常”。Java 把它们分成了三大类:
2. 三大异常类型
| 类型 | 英文名 | 特点 | 例子 |
|---|---|---|---|
| 检查型异常 | Checked Exception | 编译器强制处理(要么 try-catch,要么 throws),代表可以预见的、外部环境引起的问题 | IOException(文件找不到)、SQLException(数据库连接失败) |
| 运行时异常 | Runtime Exception | 不强制处理,通常由程序逻辑错误引起。出现这种异常说明代码写错了,应该修改代码而不是捕获 | NullPointerException(空指针)、ArrayIndexOutOfBoundsException(数组越界)、ArithmeticException(除以零) |
| 错误 | Error | 不是程序能处理的,JVM 内部严重问题 | OutOfMemoryError(内存溢出)、StackOverflowError(栈溢出) |
3. 异常处理的关键字
try:放可能出错的代码catch:捕获特定异常并处理finally:无论是否发生异常,都会执行的代码(用于释放资源)throw:手动抛出异常对象throws:声明方法可能抛出的异常,交给调用者处理
生活类比:
检查型异常就像你出门前天气预报说有雨。你必须带伞(处理异常),否则会被淋湿。
运行时异常就像你在晴天突然踩到香蕉皮滑倒。这通常是你自己不小心(代码写错),而不是环境问题。
错误就像突然地震了,你个人无能为力,只能靠整个系统(JVM)处理。
三、实操代码案例 + 场景说明
场景:从文件读取用户配置,如果文件不存在则尝试使用默认配置。
1. 检查型异常处理(必须处理)
importjava.io.*;publicclassCheckedExceptionDemo{publicstaticvoidmain(String[]args){// 方式一:try-catch 捕获处理try{FileReaderfr=newFileReader("config.txt");BufferedReaderbr=newBufferedReader(fr);Stringline=br.readLine();System.out.println("配置内容:"+line);br.close();}catch(FileNotFoundExceptione){System.out.println("文件不存在,使用默认配置");}catch(IOExceptione){System.out.println("读取文件出错:"+e.getMessage());}// 方式二:throws 向上抛出(交给调用者)// 适用于方法本身无法处理异常的情况}// 声明 throws,表示调用者必须处理publicvoidreadConfig()throwsIOException{FileReaderfr=newFileReader("config.txt");// ...}}2. 运行时异常(不强制处理,但最好修复代码)
publicclassRuntimeExceptionDemo{publicstaticvoidmain(String[]args){// 错误写法:运行时异常不处理会崩溃int[]arr={1,2,3};// System.out.println(arr[3]); // 运行会抛 ArrayIndexOutOfBoundsException// 正确做法:修复代码,而不是捕获if(args.length>0){System.out.println(args[0]);}// 如果确实需要捕获(比如防御性编程),也可以,但不推荐try{inta=10/0;}catch(ArithmeticExceptione){System.out.println("除数不能为0,已处理");}}}3. finally 与 try-with-resources
publicclassFinallyDemo{publicstaticvoidmain(String[]args){// 传统方式:手动关闭资源FileInputStreamfis=null;try{fis=newFileInputStream("data.txt");intdata=fis.read();}catch(IOExceptione){e.printStackTrace();}finally{if(fis!=null){try{fis.close();// 关闭也可能抛异常}catch(IOExceptione){e.printStackTrace();}}}// 优雅方式:try-with-resources(JDK7+)try(FileInputStreamfis2=newFileInputStream("data.txt")){intdata=fis2.read();}catch(IOExceptione){e.printStackTrace();}// 自动关闭,不需要 finally}}4. 自定义异常
// 自定义检查型异常classAgeInvalidExceptionextendsException{publicAgeInvalidException(Stringmessage){super(message);}}publicclassCustomExceptionDemo{publicstaticvoidcheckAge(intage)throwsAgeInvalidException{if(age<0||age>150){thrownewAgeInvalidException("年龄非法:"+age);}System.out.println("年龄合法");}publicstaticvoidmain(String[]args){try{checkAge(-5);}catch(AgeInvalidExceptione){System.out.println("捕获异常:"+e.getMessage());}}}四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
| 捕获异常后什么都不做(空 catch) | 问题被掩盖,难以排查 | 至少记录日志或打印堆栈 |
catch的顺序把父类放在子类前面 | 子类异常永远捕获不到 | 子类在前,父类在后 |
在finally块中return | 会覆盖try或catch中的return | 避免在finally中return |
| 用异常控制正常业务流程 | 性能极差 | 用if-else判断 |
throws声明了检查型异常却从不抛出 | 造成调用者无意义的处理 | 只声明真正会抛出的异常 |
五、面试高频考点
Q1:检查型异常和运行时异常的区别?
检查型异常编译器强制处理(
try-catch或throws),代表可恢复的外部错误(如文件不存在)。运行时异常不强制处理,代表编程错误(如空指针、越界)。Error是 JVM 内部错误。
Q2:throw和throws的区别?
throw用于实际抛出异常对象(在方法体内);throws写在方法签名后,声明该方法可能抛出的异常类型。
Q3:finally块一定会执行吗?
不一定。如果
try或catch中调用了System.exit(),或者 JVM 崩溃,finally不会执行。
Q4:try-with-resources的原理?
实现了
AutoCloseable接口的资源可以在try括号中声明,try结束后自动调用close()。编译器会生成finally块并处理异常抑制(addSuppressed)。
六、练习题
- 简答:写出至少5种运行时异常的名称。
- 编程:编写一个方法
int divide(int a, int b),当b==0时抛出自定义运行时异常DivideByZeroException。 - 代码改错:指出下面代码的问题并修正。
try{int[]arr=newint[5];System.out.println(arr[5]);}catch(Exceptione){e.printStackTrace();}catch(ArrayIndexOutOfBoundsExceptione){System.out.println("越界");}
📊 你的学习进度
- 当前:第6篇 / 共44篇 ·第二阶段:核心语法与面向对象(第5~20篇)
- ✅ 已完成:第1~5篇
- 📖 正在学:第6篇
- ⏳ 待学习:第7~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇预告
《Java面向对象简介》
内容简介:面向对象三大特征(封装、继承、多态)是什么?类和对象有什么区别?
💡 学完这篇,你将理解为什么 Java 是面向对象的语言,并能用 OOP 思想设计简单程序。
📌《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!