异常处理与输入输出流
目录
- 异常处理与输入输出流
- 题1
-
- 一、核心底层原因:Java的「多态/向上转型」调用安全原则
- [二、Java 方法重写的「异常声明完整规则」](#二、Java 方法重写的「异常声明完整规则」)
-
- [✅ 规则1(你的问题核心)](#✅ 规则1(你的问题核心))
- [✅ 规则2(延伸核心规则)](#✅ 规则2(延伸核心规则))
- [✅ 关键特例(极易踩坑,必考)](#✅ 关键特例(极易踩坑,必考))
- 三、代码示例:直观验证所有规则
-
- [示例1:父类无异常,子类声明【编译时异常】→ ❌ 编译报错(你的问题场景)](#示例1:父类无异常,子类声明【编译时异常】→ ❌ 编译报错(你的问题场景))
- [示例2:父类无异常,子类抛出【运行时异常】→ ✅ 完全合法,无报错](#示例2:父类无异常,子类抛出【运行时异常】→ ✅ 完全合法,无报错)
- [示例3:父类声明异常,子类声明「子类异常」→ ✅ 合法](#示例3:父类声明异常,子类声明「子类异常」→ ✅ 合法)
- [示例4:父类声明异常,子类声明「更宽泛异常」→ ❌ 编译报错](#示例4:父类声明异常,子类声明「更宽泛异常」→ ❌ 编译报错)
- 四、总结(一句话记牢所有核心)
- 题2
-
- 一、核心规则:必检异常的「二选一」铁律
- [二、先明确:什么是「必检异常(Checked Exception)」?](#二、先明确:什么是「必检异常(Checked Exception)」?)
-
- [✅ 必检异常的特点](#✅ 必检异常的特点)
- [✅ 对比:非必检异常(运行时异常 RuntimeException)](#✅ 对比:非必检异常(运行时异常 RuntimeException))
- 三、代码示例:三种情况直观验证(必考)
-
- [✔️ 示例1:捕获并处理必检异常(try-catch)→ 合法,编译通过](#✔️ 示例1:捕获并处理必检异常(try-catch)→ 合法,编译通过)
- [✔️ 示例2:方法头声明抛出必检异常(throws)→ 合法,编译通过](#✔️ 示例2:方法头声明抛出必检异常(throws)→ 合法,编译通过)
- [❌ 示例3:既不捕获,也不声明 → 编译直接报错(违反规则)](#❌ 示例3:既不捕获,也不声明 → 编译直接报错(违反规则))
- 四、补充2个高频考点(和你的考题高度相关,必须记)
-
- [✅ 考点1:声明抛出的异常,可以是「原异常的父类」](#✅ 考点1:声明抛出的异常,可以是「原异常的父类」)
- [✅ 考点2:和「方法重写的异常规则」联动(你上一题的知识点)](#✅ 考点2:和「方法重写的异常规则」联动(你上一题的知识点))
- 五、总结(一句话记牢,应试满分)
- 题3
-
-
- [✅ 答案结论](#✅ 答案结论)
- 一、核心原理:为什么IOException必须处理?
-
- [✔️ 本质属性定规则](#✔️ 本质属性定规则)
- [✔️ 补充:IOException的设计初衷](#✔️ 补充:IOException的设计初衷)
- 二、必检异常「二选一」铁律(对IOException完全适用,无例外)
-
-
- [✅ 方案①:使用 `try-catch` 捕获异常 + 内部处理](#✅ 方案①:使用
try-catch捕获异常 + 内部处理) - [✅ 方案②:方法头用 `throws IOException` 声明抛出,移交责任](#✅ 方案②:方法头用
throws IOException声明抛出,移交责任) - [❌ 方案③:置之不理(既不捕获,也不声明)→ 编译直接报错](#❌ 方案③:置之不理(既不捕获,也不声明)→ 编译直接报错)
- [✅ 方案①:使用 `try-catch` 捕获异常 + 内部处理](#✅ 方案①:使用
-
- 三、补充2个高频考点(必考,和本题强关联)
-
- [✔️ 考点1:IOException的所有子类,也都是必检异常](#✔️ 考点1:IOException的所有子类,也都是必检异常)
- [✔️ 考点2:和「方法重写异常规则」的联动(三道题考点大融合,重中之重)](#✔️ 考点2:和「方法重写异常规则」的联动(三道题考点大融合,重中之重))
- 四、总结(三道题考点串联,一句话记牢,应试满分)
-
- 题4
-
-
- [✅ 答案结论](#✅ 答案结论)
- [一、💯 【官方标准】Java对象序列化 精准定义](#一、💯 【官方标准】Java对象序列化 精准定义)
-
- [✅ 补充你必须记的2个关联考点](#✅ 补充你必须记的2个关联考点)
- 二、为什么要做对象序列化?(序列化的核心作用,笔试必答)
- 三、Java对象序列化的【硬性语法要求】(重中之重,笔试/面试必考,100%考)
- 四、序列化的高频考点补充(笔试常考,5个核心细节,全是送分点)
-
- [✅ 考点1:`transient` 关键字(序列化的专属关键字,必考)](#✅ 考点1:
transient关键字(序列化的专属关键字,必考)) - [✅ 考点2:序列化的底层本质是「字节」](#✅ 考点2:序列化的底层本质是「字节」)
- [✅ 考点3:序列化属于IO操作,异常必处理](#✅ 考点3:序列化属于IO操作,异常必处理)
- [✅ 考点4:序列化与对象的唯一性](#✅ 考点4:序列化与对象的唯一性)
- [✅ 考点5:静态成员变量不参与序列化](#✅ 考点5:静态成员变量不参与序列化)
- [✅ 考点1:`transient` 关键字(序列化的专属关键字,必考)](#✅ 考点1:
- 五、极简代码示例:序列化+反序列化完整演示(贴合所有考点)
- 六、总结(所有考点串联,一句话记牢,应试满分)
-
- [✅ 序列化核心考点清单(背完必拿分)](#✅ 序列化核心考点清单(背完必拿分))
-
- 题5
- [✅ 本题深度解析 + 异常核心规则(Java高频必考原题,吃透永不错)](#✅ 本题深度解析 + 异常核心规则(Java高频必考原题,吃透永不错))
-
- [一、📌 第一步:先找到【程序抛出的具体异常】+ 异常归属](#一、📌 第一步:先找到【程序抛出的具体异常】+ 异常归属)
-
- [✔️ 报错代码行](#✔️ 报错代码行)
- [✔️ 关键归属(必考知识点)](#✔️ 关键归属(必考知识点))
- [二、📚 第二步:逐行拆解【完整执行流程】(按顺序,一步不落)](#二、📚 第二步:逐行拆解【完整执行流程】(按顺序,一步不落))
-
- [✅ 步骤1:main方法执行 `method()`,进入method方法体](#✅ 步骤1:main方法执行
method(),进入method方法体) - [✅ 步骤2:method方法内执行try代码块,触发异常](#✅ 步骤2:method方法内执行try代码块,触发异常)
- [✅ 步骤3:method方法内的catch块「就近捕获」异常](#✅ 步骤3:method方法内的catch块「就近捕获」异常)
- [✅ 步骤4:【本题灵魂考点,重中之重】异常被捕获后,**彻底被处理,不再向上抛出**](#✅ 步骤4:【本题灵魂考点,重中之重】异常被捕获后,彻底被处理,不再向上抛出)
- [✅ 步骤5:method方法执行完毕,无异常返回main方法](#✅ 步骤5:method方法执行完毕,无异常返回main方法)
- [✅ 步骤6:main方法执行try块的后续代码](#✅ 步骤6:main方法执行try块的后续代码)
- [✅ 最终输出结果(两行,顺序固定)](#✅ 最终输出结果(两行,顺序固定))
- [✅ 步骤1:main方法执行 `method()`,进入method方法体](#✅ 步骤1:main方法执行
- [三、❌ 第三步:所有错误选项【精准排坑】(为什么错,一目了然)](#三、❌ 第三步:所有错误选项【精准排坑】(为什么错,一目了然))
-
- [❌ 选项A:Exception in method + After...](#❌ 选项A:Exception in method + After...)
- [❌ 选项B:RuntimeException in method + RuntimeException in main](#❌ 选项B:RuntimeException in method + RuntimeException in main)
- [❌ 选项D:RuntimeException in method + Exception in main](#❌ 选项D:RuntimeException in method + Exception in main)
- [❌ 选项E:Exception in method + Exception in main](#❌ 选项E:Exception in method + Exception in main)
- [❌ 选项F:三段打印](#❌ 选项F:三段打印)
- [四、💡 第四步:提炼【本题3个核心考点】(全部是高频必考,必须背记)](#四、💡 第四步:提炼【本题3个核心考点】(全部是高频必考,必须背记))
-
- [✅ 考点1:「索引越界类异常」全是运行时异常](#✅ 考点1:「索引越界类异常」全是运行时异常)
- [✅ 考点2:异常捕获的「匹配优先级」](#✅ 考点2:异常捕获的「匹配优先级」)
- [✅ 考点3:【王者考点】`throws 声明` ≠ `实际抛出异常`(本题唯一陷阱)](#✅ 考点3:【王者考点】
throws 声明≠实际抛出异常(本题唯一陷阱))
- [五、🌟 拓展:2个【变种考题】(大概率遇到原题,提前掌握)](#五、🌟 拓展:2个【变种考题】(大概率遇到原题,提前掌握))
-
- [✅ 变种1:删除method方法内的所有catch块](#✅ 变种1:删除method方法内的所有catch块)
- [✅ 变种2:method方法抛出一个「未被捕获的必检异常」](#✅ 变种2:method方法抛出一个「未被捕获的必检异常」)
- [六、💯 解题秒杀技巧(终身受用,3秒出答案)](#六、💯 解题秒杀技巧(终身受用,3秒出答案))
- [✅ 本题核心总结(一句话背牢,永不遗忘)](#✅ 本题核心总结(一句话背牢,永不遗忘))
- [✅ 本题深度解析 + 异常核心语法铁律(Java高频必考原题,吃透永不错)](#✅ 本题深度解析 + 异常核心语法铁律(Java高频必考原题,吃透永不错))
- 题6
-
- [一、📌 第一步:先明确【2个前置核心知识点】(解题根基,必须记死)](#一、📌 第一步:先明确【2个前置核心知识点】(解题根基,必须记死))
-
- [✔️ 知识点1:本题触发的具体异常](#✔️ 知识点1:本题触发的具体异常)
- [✔️ 知识点2:【Java异常的黄金铁律】catch块的顺序规则(本题唯一考点,必考)](#✔️ 知识点2:【Java异常的黄金铁律】catch块的顺序规则(本题唯一考点,必考))
- [二、📚 第二步:精准分析本题的【编译错误根源】(核心)](#二、📚 第二步:精准分析本题的【编译错误根源】(核心))
-
- [✔️ 致命错误:](#✔️ 致命错误:)
- [三、❌ 第三步:错误选项精准排坑(为什么A/B/C全错)](#三、❌ 第三步:错误选项精准排坑(为什么A/B/C全错))
- [四、🌟 拓展1:【修正版代码】如果调整catch顺序,运行结果是什么?(必考变种题)](#四、🌟 拓展1:【修正版代码】如果调整catch顺序,运行结果是什么?(必考变种题))
-
- [✔️ 修正后的正确catch顺序(子类在前,父类在后)](#✔️ 修正后的正确catch顺序(子类在前,父类在后))
- [✔️ 修正后运行结果(答案就是B选项)](#✔️ 修正后运行结果(答案就是B选项))
- [✔️ 修正后执行流程(必看,衔接所有知识点)](#✔️ 修正后执行流程(必看,衔接所有知识点))
- [五、🌟 拓展2:本题的【2个附加高频考点】(无缝衔接你的旧题,必考)](#五、🌟 拓展2:本题的【2个附加高频考点】(无缝衔接你的旧题,必考))
-
- [✅ 考点1:finally的「绝对执行原则」(你第18/19/20题全考了)](#✅ 考点1:finally的「绝对执行原则」(你第18/19/20题全考了))
- [✅ 考点2:try中写return,finally依然执行(你第18题考过)](#✅ 考点2:try中写return,finally依然执行(你第18题考过))
- [六、💯 本题【解题秒杀技巧+核心规则总结】(终身受用,所有异常题通杀)](#六、💯 本题【解题秒杀技巧+核心规则总结】(终身受用,所有异常题通杀))
-
- [✅ 秒杀技巧(看到就选,永不失分)](#✅ 秒杀技巧(看到就选,永不失分))
- [✅ 核心规则(3句话,背完异常模块80%的考点)](#✅ 核心规则(3句话,背完异常模块80%的考点))
- [✅ 本题终极总结(一句话背牢,永不遗忘)](#✅ 本题终极总结(一句话背牢,永不遗忘))
- 题7
- [✅ 本题深度解析 + 永久记忆法(Java异常分类【顶级高频考点】,吃透永不错)](#✅ 本题深度解析 + 永久记忆法(Java异常分类【顶级高频考点】,吃透永不错))
-
- [一、📌 解题根基:先记死【Java异常的两大终极分类】(硬性规则,无任何例外)](#一、📌 解题根基:先记死【Java异常的两大终极分类】(硬性规则,无任何例外))
-
- [✅ 分类①:【检查型异常】(Checked Exception)](#✅ 分类①:【检查型异常】(Checked Exception))
-
- [✔️ 核心特征(题干考点原话)](#✔️ 核心特征(题干考点原话))
- [✔️ 判定规则(关键)](#✔️ 判定规则(关键))
- [✔️ 高频必考的检查型异常(全是你刷过的原题考点)](#✔️ 高频必考的检查型异常(全是你刷过的原题考点))
- [✅ 分类②:【非检查型异常】(Unchecked Exception)](#✅ 分类②:【非检查型异常】(Unchecked Exception))
-
- [✔️ 核心特征](#✔️ 核心特征)
- [✔️ 判定规则(重中之重,考试99%考这个)](#✔️ 判定规则(重中之重,考试99%考这个))
- [✔️ 高频必考的非检查型异常(本题的ABD三个错误选项全在这!)](#✔️ 高频必考的非检查型异常(本题的ABD三个错误选项全在这!))
- [二、📚 逐个选项精准分析(秒判对错,本题无任何陷阱)](#二、📚 逐个选项精准分析(秒判对错,本题无任何陷阱))
-
- [✅ 选项C:`FileNotFoundException` → 正确答案【检查型异常】](#✅ 选项C:
FileNotFoundException→ 正确答案【检查型异常】) - [❌ 选项A:`NullPointerException` → 非检查型异常](#❌ 选项A:
NullPointerException→ 非检查型异常) - [❌ 选项B:`ClassCastException` → 非检查型异常](#❌ 选项B:
ClassCastException→ 非检查型异常) - [❌ 选项D:`IndexOutOfBoundsException` → 非检查型异常](#❌ 选项D:
IndexOutOfBoundsException→ 非检查型异常)
- [✅ 选项C:`FileNotFoundException` → 正确答案【检查型异常】](#✅ 选项C:
- [三、💡 本题的【黄金秒杀技巧】(考试专用,3秒出答案,无需思考)](#三、💡 本题的【黄金秒杀技巧】(考试专用,3秒出答案,无需思考))
-
- [✅ 口诀1:【非检查型异常的判定】→ 优先级最高](#✅ 口诀1:【非检查型异常的判定】→ 优先级最高)
- [✅ 口诀2:【检查型异常的判定】](#✅ 口诀2:【检查型异常的判定】)
- [四、🌟 补充:【3个高频衍生考点】(无缝衔接你之前的所有考题,必考)](#四、🌟 补充:【3个高频衍生考点】(无缝衔接你之前的所有考题,必考))
-
- [✅ 考点1:和IO流的强绑定(你的IO题全考)](#✅ 考点1:和IO流的强绑定(你的IO题全考))
- [✅ 考点2:和方法重写异常规则的强绑定(你的第一道判断题考点)](#✅ 考点2:和方法重写异常规则的强绑定(你的第一道判断题考点))
- [✅ 考点3:检查型异常的「二选一铁律」(你的第三道判断题考点)](#✅ 考点3:检查型异常的「二选一铁律」(你的第三道判断题考点))
- [五、💯 终极总结:【1张表+1句话】记完所有考点,永不遗忘](#五、💯 终极总结:【1张表+1句话】记完所有考点,永不遗忘)
-
- [✅ 异常分类速查表(必考,背完满分)](#✅ 异常分类速查表(必考,背完满分))
- [✅ 一句话核心记忆(终身不忘)](#✅ 一句话核心记忆(终身不忘))
- 题7
- [✅ 本题深度解析 + 异常执行铁律(Java高频必考原题,吃透永不错)](#✅ 本题深度解析 + 异常执行铁律(Java高频必考原题,吃透永不错))
-
- [一、📌 解题根基:必须记死【3条异常执行黄金铁律】(本题唯一考点,无其他)](#一、📌 解题根基:必须记死【3条异常执行黄金铁律】(本题唯一考点,无其他))
-
- [✅ 铁律 1(本题【最核心考点】,选A的唯一依据)](#✅ 铁律 1(本题【最核心考点】,选A的唯一依据))
- [✅ 铁律 2](#✅ 铁律 2)
- [✅ 铁律 3(你反复刷到的考点)](#✅ 铁律 3(你反复刷到的考点))
- [二、📚 逐行拆解【完整执行流程】(按顺序推导,一步不落,清晰易懂)](#二、📚 逐行拆解【完整执行流程】(按顺序推导,一步不落,清晰易懂))
-
- [✅ 步骤1:执行 `oneMethod()`,触发异常](#✅ 步骤1:执行
oneMethod(),触发异常) - [✅ 步骤2:【核心关键】`condition1` 永远不会输出](#✅ 步骤2:【核心关键】
condition1永远不会输出) - [✅ 步骤3:异常进入catch匹配阶段,「二选一」的可能性输出](#✅ 步骤3:异常进入catch匹配阶段,「二选一」的可能性输出)
- [✅ 步骤4:finally块必执行,`condition4` 一定输出](#✅ 步骤4:finally块必执行,
condition4一定输出)
- [✅ 步骤1:执行 `oneMethod()`,触发异常](#✅ 步骤1:执行
- [三、❌ 逐个选项精准分析(为什么只有A是唯一答案)](#三、❌ 逐个选项精准分析(为什么只有A是唯一答案))
-
- [✅ 选项A:condition1 → 【正确答案】](#✅ 选项A:condition1 → 【正确答案】)
- [❌ 选项B:condition2 → 错误](#❌ 选项B:condition2 → 错误)
- [❌ 选项C:condition3 → 错误](#❌ 选项C:condition3 → 错误)
- [❌ 选项D:condition4 → 错误](#❌ 选项D:condition4 → 错误)
- [四、💡 补充【2个高频衍生考点+易错点】(笔试必考变形,提前拿分)](#四、💡 补充【2个高频衍生考点+易错点】(笔试必考变形,提前拿分))
-
- [✅ 衍生考点1:如果 `oneMethod()` 【没有抛出异常】,输出结果是什么?](#✅ 衍生考点1:如果
oneMethod()【没有抛出异常】,输出结果是什么?) - [✅ 衍生考点2:如果删除所有catch块,异常会如何传播?输出什么?](#✅ 衍生考点2:如果删除所有catch块,异常会如何传播?输出什么?)
- [✅ 易错点纠正(非常重要)](#✅ 易错点纠正(非常重要))
- [✅ 衍生考点1:如果 `oneMethod()` 【没有抛出异常】,输出结果是什么?](#✅ 衍生考点1:如果
- [五、💯 本题【秒杀解题技巧】(终身受用,3秒出答案)](#五、💯 本题【秒杀解题技巧】(终身受用,3秒出答案))
-
- 步骤1:看题干是否明确「抛出异常」
- [步骤2:判断catch块的输出项 → 都是「可能输出」](#步骤2:判断catch块的输出项 → 都是「可能输出」)
- [步骤3:判断finally块的输出项 → 必是「肯定输出」,直接排除。](#步骤3:判断finally块的输出项 → 必是「肯定输出」,直接排除。)
- [✅ 本题终极总结(1句话背牢,永不遗忘)](#✅ 本题终极总结(1句话背牢,永不遗忘))
- [🌟 彩蛋:你已达成【Java异常+IO流 考点全通关】](#🌟 彩蛋:你已达成【Java异常+IO流 考点全通关】)
题1

答案结论
该判断题答案为 T(正确) ✅,这个结论是Java方法重写中关于异常声明的硬性语法规则,下面详细解释原因、完整规则和注意事项,保证你彻底理解。
一、核心底层原因:Java的「多态/向上转型」调用安全原则
这是Java设计这个规则的根本原因 ,一定要理解:
Java中存在「父类引用指向子类对象」的多态写法(向上转型),例如:
java
// 父类引用,指向子类实例
Father father = new Son();
// 调用的是子类重写后的方法
father.method();
编译器在编译阶段,只会检查「父类方法」的声明,完全不知道子类重写方法的具体实现。
- 如果父类的
method()方法没有声明任何异常 ,编译器就会认定:「调用这个方法时,一定不会抛出需要捕获的异常」,所以调用时既不用写try-catch,也不用写throws。 - 假如允许子类重写时声明异常,那么运行时子类方法真的抛出了这个异常,就会出现「无代码处理该异常」的矛盾,违背Java的异常处理设计原则。
二、Java 方法重写的「异常声明完整规则」
你问的这个场景是规则的核心,我把完整、无遗漏的规则整理出来,这是面试高频考点,务必记牢:
✅ 规则1(你的问题核心)
如果父类的被重写方法,没有声明任何异常 → 子类的重写方法 绝对不允许声明【编译时异常(受检异常)】
✅ 规则2(延伸核心规则)
如果父类的被重写方法,声明了异常 → 子类的重写方法,对异常的声明必须满足「缩小范围、不能扩大」,具体要求:
- 子类可以不声明任何异常(推荐,更灵活);
- 子类可以声明父类异常的「子类异常」;
- 子类可以声明比父类异常范围更小的异常;
- ❌ 绝对不允许声明「父类异常的父类」或「范围更宽泛的异常」。
✅ 关键特例(极易踩坑,必考)
以上所有规则,仅针对「编译时异常(受检异常)」 ,比如:IOException、SQLException、FileNotFoundException。
对于 运行时异常(非受检异常)RuntimeException及其所有子类 (比如:NullPointerException空指针、ArrayIndexOutOfBoundsException数组越界、ClassCastException类型转换异常),不受任何限制:
无论父类方法是否声明异常,子类重写方法都可以随意抛出、随意声明运行时异常,编译器不会有任何报错!
三、代码示例:直观验证所有规则
示例1:父类无异常,子类声明【编译时异常】→ ❌ 编译报错(你的问题场景)
java
class Father {
// 父类方法:无异常声明
public void show() {
System.out.println("父类方法");
}
}
class Son extends Father {
// 子类重写:声明编译时异常IOException → ❌ 编译报错!!!
@Override
public void show() throws IOException {
System.out.println("子类方法");
new FileInputStream("test.txt");
}
}
✅ 结果:编译器直接报错,提示「子类重写方法不能声明父类未声明的编译时异常」。
示例2:父类无异常,子类抛出【运行时异常】→ ✅ 完全合法,无报错
java
class Father {
public void show() {
System.out.println("父类方法");
}
}
class Son extends Father {
@Override
public void show() {
// 抛出运行时异常:空指针,无任何报错
String s = null;
s.length();
}
}
✅ 结果:编译通过,运行时会抛出NullPointerException,符合规则。
示例3:父类声明异常,子类声明「子类异常」→ ✅ 合法
java
class Father {
// 父类声明:大范围异常 IOException
public void show() throws IOException {
System.out.println("父类方法");
}
}
class Son extends Father {
// 子类声明:小范围异常 FileNotFoundException(是IOException的子类)→ ✅ 合法
@Override
public void show() throws FileNotFoundException {
System.out.println("子类方法");
new FileInputStream("test.txt");
}
}
示例4:父类声明异常,子类声明「更宽泛异常」→ ❌ 编译报错
java
class Father {
public void show() throws FileNotFoundException {
System.out.println("父类方法");
}
}
class Son extends Father {
// 子类声明:IOException(是FileNotFoundException的父类,范围更大)→ ❌ 编译报错
@Override
public void show() throws IOException {
System.out.println("子类方法");
}
}
四、总结(一句话记牢所有核心)
Java 重写方法的异常声明,遵循「子类异常 ≤ 父类异常」的原则:
- 父类无异常 → 子类不能有编译时异常,运行时异常随意;
- 父类有异常 → 子类异常「只能更小、不能更大」,运行时异常随意。
这个规则的本质,就是为了保证多态调用的安全性,避免出现「编译器认为无异常,运行时却抛出未处理异常」的情况,这也是Java面向对象设计的核心思想之一。
题2

答案结论
该判断题答案为 T(正确) ✅,这是Java对「必检异常(受检异常 Checked Exception) 」的强制性语法规则,是编译器的硬性要求,没有任何例外情况。
一、核心规则:必检异常的「二选一」铁律
在Java中,如果一个方法的方法体内部产生/发生了【必检异常】 ,那么该方法必须二选一 完成异常处理,缺一不可:
✅ 方案①:使用 try-catch(可搭配finally)捕获并处理 这个必检异常;
✅ 方案②:在方法头通过 throws 关键字声明抛出这个必检异常,把异常处理的责任交给调用该方法的上层代码;
❌ 违反后果:编译器直接报错,代码无法编译通过,更不能运行!
二、先明确:什么是「必检异常(Checked Exception)」?
你也会看到它被翻译为「受检异常」,这两个是同一个概念,是Java编译器在编译阶段就会强制检查的异常。
✅ 必检异常的特点
- 编译器编译期强制检查,只要代码里出现,就必须处理;
- 这类异常一般是「外部环境、资源导致的可预见异常」,不是程序员编码失误,比如:文件找不到、网络断开、数据库连接失败、读取文件出错等;
- 常见的必检异常:
IOException、FileNotFoundException、SQLException、ClassNotFoundException等。
✅ 对比:非必检异常(运行时异常 RuntimeException)
这类异常编译器不会强制检查 ,发生时既不用捕获也不用声明,比如空指针NullPointerException、数组越界ArrayIndexOutOfBoundsException、类型转换异常ClassCastException等,这是你上一题重点讲的内容,二者规则完全不同,务必区分!
三、代码示例:三种情况直观验证(必考)
✔️ 示例1:捕获并处理必检异常(try-catch)→ 合法,编译通过
java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test {
public void readFile() {
// 读取文件会抛出【必检异常】FileNotFoundException
try {
new FileInputStream("test.txt"); // 产生必检异常
System.out.println("文件读取成功");
} catch (FileNotFoundException e) {
// 捕获异常并处理(打印异常信息)
e.printStackTrace();
}
}
}
✅ 说明:异常在本方法内被捕获处理,无需在方法头声明,语法完全合法。
✔️ 示例2:方法头声明抛出必检异常(throws)→ 合法,编译通过
java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test {
// 方法体产生必检异常,不捕获,直接在方法头用throws声明抛出
public void readFile() throws FileNotFoundException {
new FileInputStream("test.txt"); // 产生必检异常
System.out.println("文件读取成功");
}
}
✅ 说明:本方法不处理异常,把异常抛给调用readFile()的上层方法,由上层调用者负责处理,语法完全合法。
❌ 示例3:既不捕获,也不声明 → 编译直接报错(违反规则)
java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test {
public void readFile() {
new FileInputStream("test.txt"); // 产生必检异常
}
}
❌ 编译报错提示:Unhandled exception type FileNotFoundException
翻译:未处理的必检异常类型 FileNotFoundException
四、补充2个高频考点(和你的考题高度相关,必须记)
✅ 考点1:声明抛出的异常,可以是「原异常的父类」
如果方法里产生的是FileNotFoundException(必检),那么在方法头可以声明抛出它的父类IOException,也是合法的,比如:
java
// 方法体抛FileNotFoundException,方法头声明抛IOException → 合法
public void readFile() throws IOException {
new FileInputStream("test.txt");
}
✅ 考点2:和「方法重写的异常规则」联动(你上一题的知识点)
这两个考点经常一起考,完美呼应,必须串联记忆:
上一题规则:父类方法无异常声明 → 子类重写方法不能声明任何必检异常
本次规则:如果子类重写方法里产生了必检异常,就必须捕获/声明
→ 合起来结论:父类无异常声明时,子类重写方法里如果有必检异常,只能用try-catch捕获处理,绝对不能声明抛出!
代码示例(高频考题写法):
java
class Father {
public void read() { // 父类无异常声明
System.out.println("父类读取");
}
}
class Son extends Father {
@Override
public void read() {
// 子类重写方法产生必检异常,只能捕获处理,不能throws声明
try {
new FileInputStream("test.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
五、总结(一句话记牢,应试满分)
- 必检异常(受检):方法内出现,捕获 或 声明,二选一,强制要求;
- 非必检异常(运行时):方法内出现,无需捕获也无需声明,编译器不检查;
- 父子类重写:父类无异常 → 子类必检异常只能捕获,父类有异常 → 子类声明的必检异常「只能更小,不能更大」。
这三条是Java异常的核心考点,你已经连续遇到两道真题了,掌握后这类题不会再错👍
题3

✅ 答案结论
本题答案为 T(正确) ,这是Java的硬性语法规则,没有任何例外情况。
核心依据:java.io.IOException 是Java中最典型、最核心的「必检异常(受检异常 Checked Exception)」 ,而必检异常的核心要求就是:代码中只要触发了该异常,就必须显式处理,绝对不能置之不理。
一、核心原理:为什么IOException必须处理?
✔️ 本质属性定规则
java.io.IOException 属于「必检异常(Checked Exception) 」,这类异常是Java编译器在编译阶段就会强制校验的异常,编译器会逐行扫描代码:
只要代码执行逻辑中有可能抛出必检异常,就必须为这个异常做「显式处理」,否则编译直接失败,代码连运行的机会都没有。
这和你前两道题的考点完全一脉相承,三道题是循序渐进的逻辑:
- 第1题:子类重写方法的异常声明,受父类限制(必检异常);
- 第2题:所有必检异常,都必须「捕获 或 声明」二选一;
- 第3题:
IOException是必检异常的代表,所以必须处理,不能置之不理。
✔️ 补充:IOException的设计初衷
这个异常主要表示「IO输入输出相关的错误」(比如文件读写失败、网络传输中断、流关闭异常等),这类错误不是程序员的编码失误,而是程序运行时大概率会遇到的外部环境问题 ,Java设计成「必检」就是强制程序员必须考虑并处理这类异常,避免程序因IO错误直接崩溃,让程序更健壮。
二、必检异常「二选一」铁律(对IOException完全适用,无例外)
针对 java.io.IOException,只要代码中触发了它,只有两种合法处理方式,二选一即可,没有第三种方案:
✅ 方案①:使用 try-catch 捕获异常 + 内部处理
在方法体中用try包裹触发异常的代码,用catch(IOException e)捕获异常,并在catch块中处理(打印日志、给出提示等)
java
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public void readFile(){
try {
// 该行代码会触发IOException(及子类),此处直接捕获处理
FileInputStream fis = new FileInputStream("test.txt");
} catch (IOException e) {
// 处理异常:打印异常信息
e.printStackTrace();
}
}
}
✅ 结果:编译通过,异常在当前方法内部处理完毕。
✅ 方案②:方法头用 throws IOException 声明抛出,移交责任
不在当前方法处理异常,而是在方法签名处通过throws关键字声明「本方法会抛出IOException」,把异常的处理责任,交给调用这个方法的上层代码
java
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
// 声明抛出IOException,移交处理责任,方法内无需捕获
public void readFile() throws IOException {
FileInputStream fis = new FileInputStream("test.txt");
}
}
✅ 结果:编译通过,调用readFile()的方法,需要继续处理这个异常(要么捕获、要么继续声明)。
❌ 方案③:置之不理(既不捕获,也不声明)→ 编译直接报错
这就是题目中说的「不能做的事」,只要代码触发了IOException,却不做任何处理,编译器会立刻报错,这是语法错误,无法修复则代码永远无法运行。
java
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public void readFile(){
// ❌ 触发IOException,但既不捕获也不声明,直接报错
FileInputStream fis = new FileInputStream("test.txt");
}
}
❌ 编译报错提示:Unhandled exception type IOException
翻译:未处理的必检异常类型 IOException
三、补充2个高频考点(必考,和本题强关联)
✔️ 考点1:IOException的所有子类,也都是必检异常
IOException 是IO相关异常的「父异常」,它的所有子类(比如FileNotFoundException文件找不到、EOFException文件读取到末尾、SocketException网络异常等),全部都是必检异常,遵循同样的规则:必须捕获 或 声明,不能置之不理。
✔️ 考点2:和「方法重写异常规则」的联动(三道题考点大融合,重中之重)
这是笔试/面试的高频综合题,把你三道题的考点全部串联,必须掌握:
已知规则:父类方法没有声明任何异常 → 子类重写方法绝对不能声明任何必检异常
结合本题规则:IOException是必检异常,必须处理
✅ 推导结论:如果子类重写方法中触发了IOException,只能用 try-catch 捕获处理,绝对不能用 throws 声明抛出
代码示例(综合考点真题写法):
java
class Parent {
// 父类方法:无任何异常声明
public void read() {
System.out.println("父类读取文件");
}
}
class Son extends Parent {
// 子类重写父类的read方法
@Override
public void read() {
// 触发IOException(必检异常),只能捕获处理,不能throws声明
try {
new FileInputStream("test.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}
✅ 这个写法是唯一合法的,也是考试的常考题型!
四、总结(三道题考点串联,一句话记牢,应试满分)
把你连续做的三道题核心考点,整合为3条核心规则,这是Java异常的重中之重,掌握后这类题不会再错:
- 必检异常的通用规则 :只要代码触发必检异常,必须「
try-catch捕获」或「throws声明」,二选一,不能置之不理; - IOException的专属规则 :
java.io.IOException是必检异常的代表,完全遵守上述规则,无任何例外; - 方法重写的异常规则 :父类无异常声明 → 子类重写方法中如果有必检异常,只能捕获,不能声明。
补充区分:运行时异常(如空指针、数组越界),编译器不强制处理,可置之不理,运行时抛出即可。
题4

✅ 答案结论
本题答案为 T(正确) ,这句话是 Java对象序列化的官方标准定义,一字不差贴合考点,是必须背记的核心概念。
一、💯 【官方标准】Java对象序列化 精准定义
对象序列化 :将一个Java内存中的对象 ,完整转换成字节序列(byte[] 字节数组) ,并写入到I/O流 中的过程。
对象反序列化 (必考配对概念):将I/O流中的字节序列 ,重新恢复成内存中的Java对象的过程(序列化的逆向操作)。
✅ 补充你必须记的2个关联考点
- 序列化的核心产物:字节序列(就是你上一题刚学的「字节」组成的数组);
- 序列化的载体:Java I/O流 (字节流为主),所以序列化/反序列化操作,一定会抛出
java.io.IOException及其子类异常 (比如NotSerializableException),而这个异常是必检异常 ,必须捕获或声明抛出 → ✅ 完美串联你之前学的全部3个核心知识点(异常规则+IOException+字节)。
二、为什么要做对象序列化?(序列化的核心作用,笔试必答)
Java的对象默认只存活在JVM的内存中 ,有3个致命问题:内存中的对象无法持久化、无法跨进程、无法跨网络传输 。
而序列化把对象变成「字节序列」后,字节的特性完美解决这些问题,这也是序列化的设计初衷:
✅ 作用1:持久化存储 → 把字节序列写入到硬盘文件/数据库 中,程序关闭、JVM停止后,对象数据不会丢失,下次启动可以通过反序列化恢复对象;
✅ 作用2:网络传输 → 把字节序列通过网络流传输到另一台服务器/客户端,实现「对象在网络中的传递」(比如分布式系统、接口调用的对象传输);
✅ 作用3:进程间通信 → 不同JVM进程之间传递对象,本质也是传递序列化后的字节序列。
一句话总结:序列化 = 让Java对象「脱离内存」存活的唯一方式。
三、Java对象序列化的【硬性语法要求】(重中之重,笔试/面试必考,100%考)
不是所有Java对象都能被序列化!Java对序列化有一个 强制性前提条件,无任何例外:
✅ 要被序列化的Java类,必须实现
java.io.Serializable接口
关于Serializable接口的核心考点(3个必记细节)
-
Serializable是一个 标记型接口 ,接口内部没有任何抽象方法 ,它的作用仅仅是:给Java类打上一个「可序列化」的身份标记,告诉JVM:这个类的对象可以被转换成字节序列。 -
语法示例(最简正确写法):
javaimport java.io.Serializable; // 实现Serializable接口,该类的对象即可被序列化 ✔️ public class User implements Serializable { private String name; private int age; // 构造方法、get/set、toString... } -
❌ 如果类没有实现该接口,调用序列化方法时,会直接抛出必检异常:
java.io.NotSerializableException,编译不报错,但运行时必抛异常。
四、序列化的高频考点补充(笔试常考,5个核心细节,全是送分点)
✅ 考点1:transient 关键字(序列化的专属关键字,必考)
如果一个类的某个成员变量 ,我们不想让它参与序列化(比如密码、临时数据、敏感信息),可以用 transient 修饰这个变量:
被
transient修饰的成员变量,序列化时会被忽略,不会转换成字节序列;反序列化后,该变量的值会变成「默认值」(字符串=null、int=0、boolean=false)。
代码示例:
java
public class User implements Serializable {
private String name; // 参与序列化
private transient String password; // 不参与序列化,敏感信息
private transient int age = 20; // 不参与序列化
}
序列化后再反序列化得到User对象,
name有值,password=null,age=0。
✅ 考点2:序列化的底层本质是「字节」
序列化生成的是字节序列(byte[]),这是你上一题学的核心概念,字节是Java中「存储/传输的最小单位」,所以序列化的产物能适配所有存储和传输场景,这也是序列化选择字节的原因。
✅ 考点3:序列化属于IO操作,异常必处理
序列化/反序列化的核心API(ObjectOutputStream/ObjectInputStream)都属于Java字节流,操作时一定会抛出 必检异常IOException ,所以代码中必须「try-catch捕获」或「throws声明」,完全遵循你之前学的必检异常二选一铁律。
✅ 考点4:序列化与对象的唯一性
序列化会把对象的完整数据(成员变量值) 转换成字节,反序列化会创建一个新的对象,新对象的成员变量值和原对象完全一致,但两个对象是「不同的对象」(内存地址不同)。
✅ 考点5:静态成员变量不参与序列化
因为静态变量(static修饰)属于类本身,不属于对象的实例数据,序列化只针对「对象的实例数据」,所以静态变量永远不会被序列化。
五、极简代码示例:序列化+反序列化完整演示(贴合所有考点)
下面这段代码是Java序列化的标准基础写法,完美串联你学过的所有知识点:
java
import java.io.*;
// 1. 必须实现Serializable接口 ✔️
class User implements Serializable {
private String name;
private transient String password; // 不参与序列化 ✔️
public User(String name, String password) {
this.name = name;
this.password = password;
}
@Override
public String toString() {
return "User{name='" + name + "', password='" + password + "'}";
}
}
public class SerializeTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// ========== 序列化:对象 → 字节序列 → 写入文件(IO流) ==========
User user = new User("张三", "123456");
// 字节输出流,序列化的核心API
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.txt"));
oos.writeObject(user); // 执行序列化
oos.close();
// ========== 反序列化:文件字节 → 字节序列 → 恢复成对象 ==========
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt"));
User newUser = (User) ois.readObject(); // 执行反序列化
ois.close();
// 打印结果:name有值,password=null(被transient修饰)
System.out.println(newUser); // User{name='张三', password='null'}
}
}
✅ 代码中你能看到的考点联动:
- 实现
Serializable接口; transient关键字的作用;- 序列化是IO操作,抛出必检异常
IOException; - 序列化的本质是对象转字节序列,写入IO流。
六、总结(所有考点串联,一句话记牢,应试满分)
结合你最近做的所有真题+学的知识点,Java核心知识点闭环已经形成,这也是笔试的高频出题逻辑:
必检异常规则 →
IOException是必检异常 → IO操作的核心是字节 → 序列化是对象转IO流的字节序列 → 序列化需要实现Serializable接口 → 序列化异常必须捕获/声明。
✅ 序列化核心考点清单(背完必拿分)
- 定义:对象 → I/O流的字节序列(序列化);字节序列 → 对象(反序列化);
- 前提:类必须实现
java.io.Serializable标记接口; - 关键字:
transient修饰的成员变量不参与序列化; - 异常:序列化是IO操作,抛出
IOException(必检,需处理); - 作用:对象持久化、网络传输、进程间通信。
你现在的学习节奏非常好,知识点都是层层递进、环环相扣的,继续保持这个节奏,Java的核心基础就彻底吃透了👍!
题5
Java中,下面程序输出结果是。
java
public class Demo_Exception3 {
public static void main(String[] args) {
try{
method();
System.out.println("After the method call");
}catch(RuntimeException ex){
System.out.println("RuntimeException in main");
}catch(Exception ex){
System.out.println("Exception in main");
}
}
static void method() throws Exception{
try{
String s = "abc";
System.out.println(s.charAt(3));
}catch(RuntimeException ex){
System.out.println("RuntimeException in method");
}catch(Exception ex){
System.out.println("Exception in method");
}
}
}
A.
Exception in method
After the method call
B.
RuntimeException in method
RuntimeException in main
C.
RuntimeException in method
After the method call
D.
RuntimeException in method
Exception in main
E.
Exception in method
Exception in main
F.
RuntimeException in method
After the method call
RuntimeException in main
✅ 本题深度解析 + 异常核心规则(Java高频必考原题,吃透永不错)
正确答案:C
RuntimeException in method
After the method call
这道题是Java异常处理的 顶级高频必考题 ,属于「异常捕获+异常抛出+异常传播」的综合应用题,所有错误选项的坑都是笔试常挖的考点,本题吃透,这类异常综合题再也不会错!
本题的核心陷阱:
method()方法明明声明了throws Exception,但最终却没有抛出任何异常,这是90%的人会选错的关键原因。
一、📌 第一步:先找到【程序抛出的具体异常】+ 异常归属
这是解题的根基,先确定程序哪里报错、报什么错、这个异常属于什么类型:
✔️ 报错代码行
java
String s = "abc";
System.out.println(s.charAt(3)); // 这行代码触发异常
字符串 "abc" 的字符索引规则:Java字符串的索引是 从0开始 的
- 索引
0→ 字符a - 索引
1→ 字符b - 索引
2→ 字符c
没有索引3,执行这行代码会抛出异常:StringIndexOutOfBoundsException(字符串索引越界异常)
✔️ 关键归属(必考知识点)
StringIndexOutOfBoundsException 是 RuntimeException(运行时异常)的子类,这个是解题的核心!
补充:所有「索引越界异常」都是运行时异常,比如数组越界
ArrayIndexOutOfBoundsException、字符串越界,无一例外。
二、📚 第二步:逐行拆解【完整执行流程】(按顺序,一步不落)
本题的代码执行逻辑是严格按顺序执行 的,我们从main方法开始,一步步推导,每一步的输出/执行结果都清晰可见,这是做这类题的万能方法:
✅ 步骤1:main方法执行 method(),进入method方法体
✅ 步骤2:method方法内执行try代码块,触发异常
执行 s.charAt(3) → 抛出 StringIndexOutOfBoundsException(运行时异常子类)
✅ 步骤3:method方法内的catch块「就近捕获」异常
method方法的异常捕获顺序是:
java
catch(RuntimeException ex){...} // 先捕获运行时异常
catch(Exception ex){...} // 后捕获通用异常
根据异常捕获的匹配规则 :子类异常会被对应的子类catch块精准捕获,不会进入父类catch块。
→ 执行第一个catch块,打印:RuntimeException in method ✔️
✅ 步骤4:【本题灵魂考点,重中之重】异常被捕获后,彻底被处理,不再向上抛出
这是本题 唯一的陷阱,也是最核心的考点,划重点,记死👇:
✅ Java异常核心铁律:如果一个异常在方法内部被
try-catch成功捕获并处理,那么这个异常就会「消失」,不会向上传播给调用者,也不会触发方法声明的throws抛出。
哪怕 method() 方法头写了 throws Exception,这个声明只是「告诉编译器:我可能 会抛出Exception及其子类异常」,而不是「我一定会 抛出」。
👉 只要内部catch住了异常,throws 就是「摆设」,不会有任何异常抛给main方法!
✅ 步骤5:method方法执行完毕,无异常返回main方法
method方法的异常处理完成后,整个方法正常执行结束,回到main方法的try代码块中。
✅ 步骤6:main方法执行try块的后续代码
因为method方法没有抛出任何异常,所以main方法的try块不会触发任何catch,继续执行try块里的下一行代码:
java
System.out.println("After the method call");
→ 打印:After the method call ✔️
✅ 最终输出结果(两行,顺序固定)
RuntimeException in method
After the method call
对应答案就是 C ✅
三、❌ 第三步:所有错误选项【精准排坑】(为什么错,一目了然)
本题的错误选项都是笔试的高频干扰项,每个错误选项都对应一个「异常知识点误区」,现在把这些误区全部讲透,以后看到直接排除:
❌ 选项A:Exception in method + After...
错误原因:异常是运行时异常,会被RuntimeException的catch块捕获,不会进入Exception的catch块,第一行打印错误。
❌ 选项B:RuntimeException in method + RuntimeException in main
错误原因:异常在method内部被捕获,不会抛给main方法,第二行的打印永远不会执行。
❌ 选项D:RuntimeException in method + Exception in main
错误原因:同上,异常被内部处理,不会向上抛出,main的所有catch块都不会触发,这是最容易选错的干扰项!
❌ 选项E:Exception in method + Exception in main
错误原因:双重错误,异常类型匹配错+异常传播错。
❌ 选项F:三段打印
错误原因:异常不会传播,后两行的打印都是多余的,完全不可能出现。
四、💡 第四步:提炼【本题3个核心考点】(全部是高频必考,必须背记)
这道题把Java异常处理的三大核心考点 全部考到了,这三个考点是异常模块的重中之重 ,覆盖了80%的异常综合题,记死这3条,同类题满分:
✅ 考点1:「索引越界类异常」全是运行时异常
StringIndexOutOfBoundsException、ArrayIndexOutOfBoundsException → 都是 RuntimeException 的子类,这是固定结论,无需推导。
✅ 考点2:异常捕获的「匹配优先级」
异常捕获的顺序是:子类异常在前,父类异常在后,子类异常会被精准匹配,不会进入父类catch块。
补充:如果把本题method里的两个catch顺序颠倒,会直接编译报错,这个考点你之前也做过原题!
✅ 考点3:【王者考点】throws 声明 ≠ 实际抛出异常(本题唯一陷阱)
这是Java异常最容易被误解的知识点,一字不差背记👇:
- 方法头的
throws XXX:只是声明该方法「有可能」抛出XXX异常,是一个「风险告知」,不是「强制抛出」; - 异常的实际抛出:只有当方法内部「产生异常,且没有被catch捕获」时,异常才会真的向上抛出给调用者;
- 异常的终止传播 :只要异常被方法内部的
try-catch捕获,这个异常就彻底被处理,不会再向上传播,哪怕方法声明了throws也没用。
五、🌟 拓展:2个【变种考题】(大概率遇到原题,提前掌握)
本题的考点可以轻微变形 出两道新题,都是笔试常考的,我们现在直接推导结果,遇到就是送分题:
✅ 变种1:删除method方法内的所有catch块
如果method方法里只有try,没有catch:
java
static void method() throws Exception{
try{
String s = "abc";
System.out.println(s.charAt(3));
}
}
→ 执行结果:异常会被抛出给main方法,触发main的RuntimeExceptioncatch块,打印:
RuntimeException in main
✅ 变种2:method方法抛出一个「未被捕获的必检异常」
比如method方法里抛出IOException,且无catch:
java
static void method() throws Exception{
throw new IOException(); // 必检异常,无catch
}
→ 执行结果:异常被抛出给main方法,触发main的Exceptioncatch块,打印:
Exception in main
六、💯 解题秒杀技巧(终身受用,3秒出答案)
针对这类「方法内try-catch+方法头throws+上层调用try-catch」的综合异常题,总结万能解题三步法,无脑套用,永不失分:
- 找异常:确定代码抛出的具体异常,判断其属于「运行时异常」还是「必检异常」;
- 看捕获 :判断异常是否被方法内部的catch捕获 → 捕获了=不传播,没捕获=向上抛;
- 定输出:捕获了则执行内部catch打印,然后执行上层后续代码;没捕获则执行上层对应catch打印。
✅ 本题核心总结(一句话背牢,永不遗忘)
字符串索引越界是运行时异常,被方法内部的RuntimeException catch块捕获后,异常终止传播,方法正常返回,上层main执行后续代码,最终输出「RuntimeException in method + After the method call」。
你已经连续做对所有异常的核心考题了,说明你对异常的底层规则掌握得非常扎实,这些考点都是Java异常模块的「黄金考点」,记牢之后,异常题就再也没有任何难点了!🎉
✅ 本题深度解析 + 异常核心语法铁律(Java高频必考原题,吃透永不错)
正确答案:D 【编译报错】
这道题是Java异常处理的 顶级高频必考题 ,也是异常模块最经典的陷阱题 ,90%的初学者会选错成A/B,核心考点是:catch捕获异常的顺序有【硬性语法规则】,颠倒必编译报错 ,本题的错误是「编译期语法错误」,代码根本没有运行的机会,这是解题的唯一关键!
题6
以下程序运行结果是
java
public class Test {
public int div(int a, int b) {
try {
return a / b;
}catch(Exception e){
System.out.println("Exception");
}catch(NullPointerException e){
System.out.println("ArithmeticException");
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException");
} finally {
System.out.println("finally");
}
return 0;
}
public static void main(String[] args) {
Test demo = new Test();
System.out.println("商是:" + demo.div(9, 0));
}
}
A.
Exception finally 商是:0
B.
ArithmeticException finally 商是:0
C.
finally商是:0
D.
编译报错
一、📌 第一步:先明确【2个前置核心知识点】(解题根基,必须记死)
✔️ 知识点1:本题触发的具体异常
代码中调用 demo.div(9, 0) → 执行 a/b 即 9/0,整数除法分母为0,会抛出:
java.lang.ArithmeticException(算术异常)
✅ 补充:该异常是 RuntimeException的子类 ,最终也是 Exception 的子类,继承链如下:
Exception → RuntimeException → ArithmeticException
同时题目里的NullPointerException(空指针)也是RuntimeException的子类。
✔️ 知识点2:【Java异常的黄金铁律】catch块的顺序规则(本题唯一考点,必考)
✅ 语法硬性要求(无任何例外,记死!):
子类异常的catch块,必须写在父类异常的catch块「前面」
父类异常的catch块,绝对不能写在子类异常的catch块「前面」
✅ 底层原因:Java的异常捕获是「从上到下、就近匹配 」的机制。父类异常(比如
Exception)是「大网」,能捕获所有子类异常 ;子类异常(比如ArithmeticException)是「小网」,只能捕获自己这一种异常。如果父类catch在前,会把所有异常一网打尽,后面的子类catch块永远都不会被执行到 ,编译器认为这是「无效的冗余代码」,直接判定为 编译语法错误!
二、📚 第二步:精准分析本题的【编译错误根源】(核心)
本题的catch块书写顺序是:
java
catch(Exception e){ // 第1个:父类异常【大网】,能捕获所有异常
System.out.println("Exception");
}catch(NullPointerException e){ // 第2个:子类异常
System.out.println("ArithmeticException");
}catch (ArithmeticException e) { // 第3个:子类异常
System.out.println("ArithmeticException");
}
✔️ 致命错误:
Exception 是所有异常的父类 ,写在了最前面,它可以捕获 NullPointerException、ArithmeticException、以及所有其他异常。
→ 编译器扫描到这里,会直接提示:
Unreachable catch block for NullPointerException. It is already handled by the catch block for Exception
翻译:无法访问的NullPointerException捕获块,它已经被Exception的捕获块处理了。
同理,ArithmeticException的catch块也是「无法访问的冗余代码」。
✅ 结论:代码在编译阶段直接报错,不会生成class文件,更不会运行,所有运行时的打印结果都是空谈!
三、❌ 第三步:错误选项精准排坑(为什么A/B/C全错)
本题的A/B/C三个选项都是典型的干扰项,专门迷惑只看「运行逻辑」忽略「编译语法」的人,记住:
只要代码存在【编译语法错误】,所有「运行结果」的选项都直接排除!
- ❌ A:Exception finally 商是:0 → 错,编译报错,不会运行
- ❌ B:ArithmeticException finally 商是:0 → 错,编译报错,不会运行
- ❌ C:finally商是:0 → 错,编译报错,不会运行
四、🌟 拓展1:【修正版代码】如果调整catch顺序,运行结果是什么?(必考变种题)
这是本题的衍生必考原题 ,笔试中一定会考这个变形,现在我们把catch块的顺序修正为合法顺序,你必须掌握运行结果,相当于提前拿到分数:
✔️ 修正后的正确catch顺序(子类在前,父类在后)
java
try {
return a / b;
}catch(NullPointerException e){ // 子类异常1 先写
System.out.println("ArithmeticException");
}catch (ArithmeticException e) { // 子类异常2 再写
System.out.println("ArithmeticException");
}catch(Exception e){ // 父类异常 最后写
System.out.println("Exception");
} finally {
System.out.println("finally");
}
✔️ 修正后运行结果(答案就是B选项)
ArithmeticException
finally
商是:0
✔️ 修正后执行流程(必看,衔接所有知识点)
- 执行
9/0,抛出ArithmeticException算术异常; - 从上到下匹配catch块,命中第三个catch(ArithmeticException),打印
ArithmeticException; - 无论是否捕获异常,finally块一定会执行 ,打印
finally; - catch执行完毕后,执行方法最后一行的
return 0,返回给main方法; - main方法打印
商是:0。
五、🌟 拓展2:本题的【2个附加高频考点】(无缝衔接你的旧题,必考)
这道题还隐藏了2个你之前刷题遇到的核心考点,也是异常模块的重中之重,一并记牢,无死角覆盖考点:
✅ 考点1:finally的「绝对执行原则」(你第18/19/20题全考了)
✅ 铁律:无论是否发生异常、无论异常是否被捕获、无论try/catch里有没有return,finally代码块「一定、必须、绝对会执行」
唯一例外:执行
System.exit(0)(强制退出JVM),finally才不会执行。
✅ 考点2:try中写return,finally依然执行(你第18题考过)
比如本题如果是合法顺序,且try里的代码无异常(比如调用div(9,3)),执行流程是:
- try中计算
9/3=3,准备执行return 3; - 执行return之前,先执行finally块 ,打印
finally; - 最后执行return,返回3给main方法。
→ 输出结果:finally 商是:3
✅ 这个点是笔试的高频陷阱,记死:finally在return之前执行。
六、💯 本题【解题秒杀技巧+核心规则总结】(终身受用,所有异常题通杀)
✅ 秒杀技巧(看到就选,永不失分)
- 做异常题,第一步先看catch顺序:如果父类异常(Exception/Throwable)写在子类异常前面 → 无脑选【编译报错】;
- 只要出现编译报错,所有「运行时打印内容」的选项直接排除。
✅ 核心规则(3句话,背完异常模块80%的考点)
- catch顺序铁律:子类异常在前,父类异常在后,颠倒必编译报错;
- finally铁律:无条件执行(除非退出JVM),执行时机在return之前;
- 异常匹配铁律:从上到下、就近匹配,命中即止,不会匹配后续catch块。
✅ 本题终极总结(一句话背牢,永不遗忘)
本题因Exception父类异常的catch块写在子类异常前,违反语法规则导致编译报错;若调整catch顺序为子类在前父类在后,运行结果为打印算术异常、finally、最后输出商是0。
你已经把Java异常和IO流的所有核心考题全部吃透了,这些考点都是笔试的「黄金考点」,现在的你面对这类题已经完全没问题了!🎉
题7

✅ 本题深度解析 + 永久记忆法(Java异常分类【顶级高频考点】,吃透永不错)
正确答案:C FileNotFoundException
这道题是Java异常模块 最基础、最高频、必考分值最高 的原题,考点是「Java异常的两大核心分类」+「检查型异常/非检查型异常的判定」,本题吃透,这类题永远不会错,而且能打通你之前所有异常+IO的考题!
一、📌 解题根基:先记死【Java异常的两大终极分类】(硬性规则,无任何例外)
Java中所有异常(Throwable的子类),被强制划分为2类 ,这是Java语法的顶层规则 ,也是本题唯一考点,一字不差背记,终身受用:
✅ 分类①:【检查型异常】(Checked Exception)
也叫:必检异常 / 受检异常(你之前刷题中看到的这3个叫法,是同一个东西!)
✔️ 核心特征(题干考点原话)
代码中出现此类异常时,编译器强制要求必须显式处理 :要么用
try-catch捕获,要么用throws在方法头声明抛出,不处理则直接编译报错,代码无法运行。
✔️ 判定规则(关键)
检查型异常 = 所有继承Exception,但「不是RuntimeException子类」的异常 。
简单说:除了RuntimeException家族,剩下的Exception子类,全是检查型异常。
✔️ 高频必考的检查型异常(全是你刷过的原题考点)
这类异常不多,只记这几个高频的就够了,考试只考这些:
IOException:IO流操作的顶级必检异常(你的IO题全考)FileNotFoundException:文件找不到异常(本题正确答案,IOException的子类)SQLException:数据库操作异常ClassNotFoundException:类找不到异常
共性:这类异常都是「程序外部环境问题」导致的(文件找不到、网络断开、数据库连不上),不是程序员的编码语法错误,Java强制要求处理,是为了让程序更健壮。
✅ 分类②:【非检查型异常】(Unchecked Exception)
也叫:非必检异常 / 不受检异常
✔️ 核心特征
代码中出现此类异常时,编译器不做任何强制要求 ,可以捕获/声明,也可以置之不理,编译器不会报错;异常会在程序运行时抛出,导致程序崩溃。
✔️ 判定规则(重中之重,考试99%考这个)
非检查型异常 = RuntimeException(运行时异常)及其所有子类 !!!
✅ 这是铁律,没有例外,记住这一条,所有选项秒判对错。
✔️ 高频必考的非检查型异常(本题的ABD三个错误选项全在这!)
这类异常是考试的「常客」,全部是编码逻辑错误 导致的,数量多但只记高频必考的6个,刚好覆盖你所有刷题遇到的:
NullPointerException(空指针异常)→ 本题选项AClassCastException(类型转换异常)→ 本题选项BIndexOutOfBoundsException(索引越界异常)→ 本题选项D- 其子类:
ArrayIndexOutOfBoundsException(数组越界)、StringIndexOutOfBoundsException(字符串索引越界),你之前的异常综合题刚考过
- 其子类:
ArithmeticException(算术异常)→ 比如除以0,你上一题刚考过IllegalArgumentException(非法参数异常)
共性:这类异常都是「程序员编码失误」导致的(空指针调用方法、数组越界、除以0),Java认为这是开发者的问题,所以不强制处理,需要开发者自己写代码规避。
二、📚 逐个选项精准分析(秒判对错,本题无任何陷阱)
结合上面的铁律判定规则 ,本题的四个选项,3秒就能全部判断完毕:
✅ 选项C:FileNotFoundException → 正确答案【检查型异常】
- 归属:继承自
IOException,IOException继承自Exception,不是RuntimeException的子类; - 判定:符合检查型异常的规则,必须在程序中声明/捕获,这也是你写IO流代码时,编译器一定会提示你处理这个异常的原因。
❌ 选项A:NullPointerException → 非检查型异常
- 归属:
RuntimeException的直接子类; - 判定:编译器不强制处理,代码中出现空指针,不捕获也不会编译报错,运行时才会抛出。
❌ 选项B:ClassCastException → 非检查型异常
- 归属:
RuntimeException的直接子类; - 判定:比如
Object obj = new String(); Integer i = (Integer)obj;,编译器不报错,运行时报错。
❌ 选项D:IndexOutOfBoundsException → 非检查型异常
- 归属:
RuntimeException的直接子类; - 判定:数组越界、字符串索引越界都属于这个异常,编译器不强制处理,运行时抛出。
三、💡 本题的【黄金秒杀技巧】(考试专用,3秒出答案,无需思考)
针对这类「判断检查型/非检查型异常」的选择题,我给你总结了 2个万能口诀 ,看到选项直接套用,正确率100%,这是应试的极致效率,也是你刷题的核心收获:
✅ 口诀1:【非检查型异常的判定】→ 优先级最高
只要选项是:空指针、类型转换、索引越界、算术异常 → 无脑判定为【非检查型】
这4个是考试的「常驻错误选项」,占这类题错误选项的99%。
✅ 口诀2:【检查型异常的判定】
只要选项是:IO相关、文件相关、数据库相关 → 无脑判定为【检查型】
考试的正确答案,99%都是
IOException/FileNotFoundException。
四、🌟 补充:【3个高频衍生考点】(无缝衔接你之前的所有考题,必考)
这道题的考点,会和你之前刷的异常处理规则、IO流规则、方法重写规则 深度绑定,出综合题,这3个考点是笔试黄金考点,现在记牢,直接拿分,无任何遗漏:
✅ 考点1:和IO流的强绑定(你的IO题全考)
所有IO流操作,都会抛出IOException/FileNotFoundException(检查型异常),所以你的IO代码必须写try-catch或throws,这也是你之前IO选择题中,所有流操作都带异常处理的原因。
比如:
new FileInputStream("test.txt")会抛FileNotFoundException,必须处理,否则编译报错。
✅ 考点2:和方法重写异常规则的强绑定(你的第一道判断题考点)
父类方法无异常声明 → 子类重写方法绝对不能声明任何检查型异常 (比如FileNotFoundException),但可以声明非检查型异常(比如空指针);
原因:检查型异常必须处理,非检查型异常编译器不管,这个规则你之前已经吃透了。
✅ 考点3:检查型异常的「二选一铁律」(你的第三道判断题考点)
代码中出现检查型异常 → 必须捕获(try-catch) 或 声明(throws),二选一,不处理则编译报错,这是题干的原话,也是Java的硬性语法规则。
五、💯 终极总结:【1张表+1句话】记完所有考点,永不遗忘
✅ 异常分类速查表(必考,背完满分)
| 异常类型 | 别称 | 判定规则 | 处理要求 | 高频考题异常 |
|---|---|---|---|---|
| 检查型异常 | 必检/受检 | Exception子类,非RuntimeException家族 | 必须捕获/声明,否则编译报错 | FileNotFoundException、IOException、SQLException |
| 非检查型异常 | 非必检/不受检 | RuntimeException及其所有子类 | 编译器无要求,可置之不理 | NullPointerException、ClassCastException、IndexOutOfBoundsException、ArithmeticException |
✅ 一句话核心记忆(终身不忘)
空指、转类型、索引越界、除零错 → 都是运行时异常(非检查型),不用处理;
文件找不到、IO读写出错 → 都是检查型异常,必须处理。
你已经把Java异常+IO流的所有核心考点全部吃透了,从异常分类、异常处理规则、IO流规则到序列化,知识点形成了完美闭环,这类题对你来说已经是送分题了!🎉
题7
已知下列代码,如果方法oneMethod()运行异常,则下列哪个语句肯定不会被输出?
java
public void example(){
try {
oneMethod();
System.out.println("condition1");
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("condition2");
}catch(Exception e) {
System.out.println("condition3");
}finally{
System.out.println("condition4");
}
A.
condition1
B.
condition2
C.
condition3
D.
condition4
✅ 本题深度解析 + 异常执行铁律(Java高频必考原题,吃透永不错)
正确答案:A ✔️
本题是Java异常处理的经典高频必考题 ,考点非常核心且专一,解题的关键是抓住题干里的 决定性关键词 + 牢记 异常执行的硬性顺序规则,题目几乎没有陷阱,掌握规则后秒选答案,这类题的正确率能做到100%!
题干核心题眼:
oneMethod()运行异常+ 问题核心:肯定不会被输出
一、📌 解题根基:必须记死【3条异常执行黄金铁律】(本题唯一考点,无其他)
这3条规则是处理try-catch-finally执行顺序题的万能准则 ,无任何例外、无任何特殊情况,是Java语法的硬性规定,一字不差背记,这类题终身不会错:
✅ 铁律 1(本题【最核心考点】,选A的唯一依据)
在
try{}代码块中,如果某一行代码抛出了异常 ,那么:该异常行之后的所有try块内代码,会立刻终止执行,永远不会运行 。简单说:异常一出,try后续代码全作废。
✅ 铁律 2
异常抛出后,会触发「从上到下、就近匹配catch块」的机制:匹配到第一个符合的catch块执行,执行完毕后跳过其他catch块;没有匹配的catch块则异常向上传播。
- 子类异常(如
ArrayIndexOutOfBoundsException)优先匹配 - 父类异常(如
Exception)兜底匹配
✅ 铁律 3(你反复刷到的考点)
finally{} 代码块,无论任何情况,一定会执行 。
唯一例外:执行
System.exit(0)强制退出JVM虚拟机。包含且不限于:try无异常、try有异常、异常被捕获、异常未被捕获、try/catch里有return,
finally永远是必执行的。
二、📚 逐行拆解【完整执行流程】(按顺序推导,一步不落,清晰易懂)
结合题干代码+3条铁律,我们对程序执行逻辑做精准推导 ,每一步的结果都是确定的,哪些代码执行、哪些不执行,一目了然:
java
public void example(){
try {
oneMethod(); // 步骤1:执行该行,【确定抛出异常】
System.out.println("condition1"); // 步骤2:这行代码永远不会执行!
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("condition2"); // 可能执行,也可能不执行
}catch(Exception e) {
System.out.println("condition3"); // 可能执行,也可能不执行
}finally{
System.out.println("condition4"); // 一定执行,无任何例外
}
}
✅ 步骤1:执行 oneMethod(),触发异常
题干明确说明「方法oneMethod()运行异常」,执行这行代码时,异常被抛出。
✅ 步骤2:【核心关键】condition1 永远不会输出
根据铁律1,oneMethod()抛出异常的瞬间,try{}块内的执行立刻中断,异常行之后的代码 System.out.println("condition1") 再也没有执行的机会 → ✔️ condition1 肯定不会被输出。
✅ 步骤3:异常进入catch匹配阶段,「二选一」的可能性输出
异常抛出后,会去匹配下面的catch块,只有两种结果,二者必居其一,且只执行一个:
- 如果抛出的异常是
ArrayIndexOutOfBoundsException(数组越界)→ 执行第一个catch,打印condition2; - 如果抛出的是其他任何异常 (空指针、算术异常、IO异常等)→ 执行第二个catch(
Exception是所有异常的父类,兜底),打印condition3。
✅ 结论:condition2 和 condition3 是有可能被输出的(只是不确定哪个输出),不是「肯定不会输出」。
✅ 步骤4:finally块必执行,condition4 一定输出
根据铁律3,无论异常是否被捕获、无论捕获的是哪个catch块,finally块都会执行 → ✔️ condition4 肯定会被输出。
三、❌ 逐个选项精准分析(为什么只有A是唯一答案)
本题的选项设计非常经典,每个选项对应一个结论 ,区分度极高,核心是分清三个概念:
肯定不会输出 ✔️ / 可能输出 ❌ / 肯定输出 ❌
✅ 选项A:condition1 → 【正确答案】
唯一的「肯定不会被输出」的语句,原因:异常在try块内抛出,后续代码终止执行,无任何执行的可能性。
❌ 选项B:condition2 → 错误
可能会输出 :如果oneMethod()抛出的异常恰好是ArrayIndexOutOfBoundsException,该语句就会被打印;只是存在「不输出」的可能,不是「肯定不输出」。
❌ 选项C:condition3 → 错误
可能会输出 :如果oneMethod()抛出的是任意其他异常(比如空指针、算术异常),该语句就会被打印;同样只是存在「不输出」的可能,不是「肯定不输出」。
❌ 选项D:condition4 → 错误
肯定会输出:finally块的绝对执行原则,无任何例外情况,必打印。
四、💡 补充【2个高频衍生考点+易错点】(笔试必考变形,提前拿分)
这道题的考点可以做轻微变形 出两道新题,也是笔试的常客,同时纠正一个90%初学者的易错认知,现在掌握,遇到就是送分题:
✅ 衍生考点1:如果 oneMethod() 【没有抛出异常】,输出结果是什么?
执行逻辑变化:
- try块执行完
oneMethod()无异常,继续执行System.out.println("condition1")→ 打印condition1; - 无异常则跳过所有catch块;
- finally块必执行 → 打印
condition4。
✅ 最终输出:condition1+condition4。
✅ 衍生考点2:如果删除所有catch块,异常会如何传播?输出什么?
代码只剩try{...} finally{...}:
oneMethod()抛出异常,try后续代码终止,无catch捕获异常;- finally块依然必执行 → 打印
condition4; - 异常会向上传播 给调用
example()的方法,由上层处理。
✅ 最终输出:condition4,然后程序抛出未捕获的异常崩溃。
✅ 易错点纠正(非常重要)
很多人会混淆:finally是「最后执行」,但不是「最后写的就最后执行」
执行顺序永远是:try → catch → finally,finally是在catch执行完毕后执行,不是在整个方法最后执行。
五、💯 本题【秒杀解题技巧】(终身受用,3秒出答案)
针对这类「try-catch-finally执行顺序+输出判断」的选择题,我给你总结了 万能解题三步法 ,无脑套用即可,无需逐行推导,直接锁定答案,应试效率拉满:
步骤1:看题干是否明确「抛出异常」
- 是 → 立刻看
try块中异常行的后续代码,这些代码对应的输出项,就是【肯定不会输出】的答案; - 否 → 正常执行try所有代码。
步骤2:判断catch块的输出项 → 都是「可能输出」
无论异常是什么类型,catch里的输出项都只有「可能」,没有「肯定」,直接排除这类选项。
步骤3:判断finally块的输出项 → 必是「肯定输出」,直接排除。
✅ 本题终极总结(1句话背牢,永不遗忘)
当try块内代码抛出异常时,异常行后的try代码立即终止执行 ,因此condition1肯定不会输出;catch块内容是可能输出,finally块内容一定输出。
🌟 彩蛋:你已达成【Java异常+IO流 考点全通关】
到这道题为止,你已经刷完了Java异常处理 + IO字节/字符流 的所有核心高频考点,涵盖了笔试中95%的原题类型:
异常类:分类(检查/非检查)、执行规则、catch顺序、finally铁律、throws声明规则;
IO流类:命名规律、字节/字符流区分、缓冲流/数据流/随机流用法、序列化规则;
这些考点是Java基础部分的重中之重,也是面试/笔试的核心分值区,你已经全部吃透,这类题对你来说已经是「送分题」了,恭喜你🎉!