09、Java 基础硬核复习:异常处理(容错机制)的核心逻辑与面试考点
一、核心知识体系:异常处理的"三大支柱"
本章的知识围绕"异常"的定义、分类、处理方式 展开,可以归纳为三大支柱 :异常体系结构 、异常处理方式 、自定义异常。
1. 异常的体系结构:Throwable 是"根",Error 与 Exception 分家
Java 中所有异常的根类是 java.lang.Throwable,它分为两大子类:
Error(错误) :JVM 无法解决的严重问题(如OutOfMemoryError、StackOverflowError)。这类错误通常由系统资源耗尽或底层错误导致,一般不需要程序员处理(因为程序无法恢复)。Exception(异常) :可处理的异常,分为两类:- 运行时异常(RuntimeException) :编译器不强制检查,程序运行时可能抛出(如
NullPointerException、ArrayIndexOutOfBoundsException)。这类异常通常由程序逻辑错误导致(如空指针、数组越界),应通过修正代码解决,而非捕获。 - 编译时异常(非 RuntimeException) :编译器强制检查,必须处理(如
IOException、SQLException)。这类异常通常由外部因素导致(如文件不存在、数据库连接失败),必须通过 try-catch 或 throws 处理,否则编译不通过。
- 运行时异常(RuntimeException) :编译器不强制检查,程序运行时可能抛出(如
2. 异常处理方式:try-catch-finally 与 throws
Java 提供两种方式处理异常:本地处理(try-catch-finally)和抛出(throws)。
(1)try-catch-finally:本地处理异常
try-catch-finally 是最常用的异常处理方式,用于在方法内部捕获并处理异常,保证程序继续运行。
-
语法:
javatry { // 可能抛出异常的代码(如文件读取、数据库操作) } catch (ExceptionType1 e) { // 处理 ExceptionType1 异常(如打印错误信息、恢复默认值) } catch (ExceptionType2 e) { // 处理 ExceptionType2 异常(如记录日志) } finally { // 无论是否发生异常,都会执行的代码(如关闭文件流、数据库连接) } -
关键点:
catch块可以捕获多个异常(JDK 7 后支持catch (ExceptionType1 | ExceptionType2 e),简化代码)。finally块一定会执行 (除非调用System.exit(0)强制退出 JVM),常用于释放资源(如关闭 IO 流、数据库连接)。- 执行顺序:
try块 →catch块(若有异常)→finally块。即使catch中有return,finally也会执行(且finally中的return会覆盖try/catch中的return)。
(2)throws:声明异常,由调用者处理
如果方法无法处理异常,可以通过 throws 将异常抛给调用者,让调用者决定如何处理。
- 语法 :在方法声明中抛出异常,格式为
public void method() throws ExceptionType。 - 关键点 :
- 方法重写时,子类方法不能抛出比父类更多的编译时异常 (如父类抛出
IOException,子类不能抛出SQLException),但可以抛出更少的或运行时异常(因为运行时异常编译器不强制检查)。 - 调用者必须处理
throws声明的异常(要么try-catch,要么继续throws)。
- 方法重写时,子类方法不能抛出比父类更多的编译时异常 (如父类抛出
3. 手动抛出异常与自定义异常:业务场景的"精准控制"
-
throw:手动抛出异常,格式为throw new ExceptionType("错误信息"),用于程序逻辑判断(如参数非法时抛出异常)。例如,学生注册时年龄小于 18 岁,可以抛出自定义异常AgeOutOfBoundsException。 -
自定义异常 :继承
Exception(检查异常)或RuntimeException(运行时异常),用于特定业务场景。自定义异常需要提供无参构造器和带参构造器(调用super(msg)传递错误信息)。例如:javapublic class AgeOutOfBoundsException extends RuntimeException { public AgeOutOfBoundsException() { super("年龄不能小于 18 岁"); } public AgeOutOfBoundsException(String message) { super(message); } }
二、高频面试考点:必考"死穴",掌握这些=掌握异常处理的核心
本章的面试题非常经典,主要考察对概念的混淆辨析,以下是必考考点:
1. final、finally、finalize 的区别(必考题)
这三个词长得像,但作用完全不同:
final:修饰符,用于修饰类(不可继承)、方法(不可重写)、变量(不可变)。例如,final class A {}表示类A不能被继承。finally:异常处理的关键字,保证代码块一定执行(通常用于资源释放)。例如,finally { file.close(); }确保文件流被关闭。finalize:Object类的方法,垃圾回收器回收对象前会调用(JDK 9 已标记为过时,不推荐使用)。
2. throw 和 throws 的区别
throw:动作 ,写在方法体 中,后面跟异常对象 (如throw new NullPointerException("空指针"))。throws:声明 ,写在方法签名 (参数列表)后,后面跟异常类名 (如public void method() throws IOException)。
3. 运行时异常 vs 编译时异常
- 运行时异常 :编译器不强制检查,程序运行时可能抛出,通常由逻辑错误导致。常见例子:
NullPointerException(空指针)ArrayIndexOutOfBoundsException(数组越界)ClassCastException(类型转换异常)NumberFormatException(数字格式异常)ArithmeticException(算术异常,如除以 0)
- 编译时异常 :编译器强制检查,必须处理。常见例子:
IOException(文件操作异常)SQLException(数据库异常)ClassNotFoundException(类未找到异常)
4. finally 中的代码一定会执行吗?
-
答案 :会 。
finally会在return语句执行之后、返回结果之前执行。例如:javapublic static int test() { try { return 1; // 返回 1 } catch (Exception e) { return 2; // 不会执行 } finally { return 3; // 覆盖前面的 return,最终返回 3 } } -
特例 :只有一种情况
finally不执行------在try/catch中调用了System.exit(0)(强制退出 JVM)。
5. 方法重写的异常规则
子类重写父类方法时,对抛出的异常有严格限制,遵循"两同两小一大"中的"一小":
- 子类重写的方法抛出的异常类型,必须小于等于父类被重写方法抛出的异常类型(或者不抛出)。
- 例如,父类方法
public void read() throws IOException,子类重写时可以throws IOException或throws FileNotFoundException(FileNotFoundException是IOException的子类),但不能throws SQLException(SQLException不是IOException的子类)。
三、学习建议:从"理论"到"实践"的跃迁
- 异常体系结构 :用"生活例子"理解(如
Error是"房子塌了",Exception是"钥匙忘带了"),区分运行时异常("不小心摔了")和编译时异常("没带身份证进机场")。 - try-catch-finally :多写代码,测试
finally的执行顺序(如try中有return,catch中有return,finally中有return的情况)。 - throws 与 throw :结合方法重写,理解"子类不能抛更多检查异常"的规则(如父类
readFile()抛出IOException,子类readFile()不能抛出SQLException)。 - 自定义异常:尝试为"学生注册""几何图形面积"等场景写自定义异常,理解"业务精准控制"的意义。
- 资源关闭 :虽然思维导图主要讲
finally,但建议了解 JDK 7 引入的try-with-resources语法(自动关闭资源),这是现代 Java 开发的标准写法(如try (FileInputStream fis = new FileInputStream("file.txt")) {})。
四、总结:异常处理是"健壮性"的关键
第09章是 Java 程序的"容错机制",它将你从"如何写代码"带入"如何处理错误"的层面。掌握异常处理,你就能写出更健壮的程序,也能在面试中轻松应对"Java 基础"的"硬核"问题。
记住,异常处理不是"掩盖错误",而是"优雅地处理错误"------这一章,就是教你如何用 Java 的语法,让程序在遇到错误时,依然能稳定运行。