Java 期末复习全套资料:模拟卷 + 答案详解
这是一份为你精心定制的Java 期末模拟试卷。
出题策略: 这份模拟卷严格参照你提供的真题结构、难度分布和考点覆盖范围进行编写。通过“同构题”(考点相同但题目形式不同)和“进阶题”(考点相关但略有延伸)的组合,帮助你检测复习是否存在死角。
Java 期末模拟仿真卷
考试时间: 120分钟
满分: 100分
第一部分:简答与程序分析题 (每题 5 分,共 55 分)
1. 分析下列程序,并简述 String 对象的不可变性(Immutability),并给出运行结果。
Java
1 | public class StringTest { |
2. 简述 Java 中 static 关键字的作用。请分别说明 static 修饰成员变量、成员方法以及静态代码块时的特点和执行时机。
3. 在处理大量无需重复且不要求顺序的数据时,你会选择 Java 集合框架中的 HashSet 还是 TreeSet?请从底层数据结构(Hash表 vs 红黑树)和性能角度(时间复杂度)进行论述。
4. 简述 Java 中四种访问权限修饰符(private, default/friendly, protected, public)的作用范围区别。
5. 简述线程生命周期中的 sleep() 方法和 wait() 方法的区别。如果线程类已经实现了 Runnable 接口,是否还能通过继承 Thread 类的方式创建线程?为什么?
6. 分析下列程序,指出多态在其中的体现。请问 output 方法中的 b.show(b) 调用的是哪个类的方法?并写出最终的输出结果。
Java
1 | class A { |
7. 简述 Hashtable 与 HashMap 的区别(提示:从线程安全、null 值支持、效率三个方面回答)。
8. 分析下列程序关于 try-catch-finally 块中 return 语句的执行顺序,并写出运行结果。
Java
1 | public class ReturnTest { |
9. 简述 Java 中的受检异常(Checked Exception)和运行时异常(Runtime Exception)的区别,并各举一个例子。
10. 分析下列程序的初始化顺序(静态代码块 vs 构造代码块 vs 构造方法),并写出运行结果。
Java
1 | class Base { |
11. 下列代码试图实现一个简单的银行账户取款操作。在多线程环境下,该代码是否存在线程安全问题?如果存在,请指出问题所在,并使用 synchronized 关键字给出一种修改方案(可以修饰方法或代码块)。
Java
1 | class Account { |
第二部分:编程题 (共 45 分)
1. (15分) 集合与排序
定义一个学生类 Student,满足以下要求:
- (1) 包含成员变量:姓名
name(String),成绩score(int)。 - (2) 提供带参构造方法初始化姓名和成绩。
- (3) 覆写
toString()方法,返回格式为 “Name: xxx, Score: xxx”。 - (4) 在
main方法中,创建 4 个学生对象存入ArrayList中。 - (5) 核心要求:使用
Collections.sort方法对学生按照成绩从高到低进行排序。如果成绩相同,则按照姓名的字典序(字母顺序)排列。最后遍历集合打印排序后的结果。- 提示:可以使用
Comparator接口或让Student类实现Comparable接口。
- 提示:可以使用
2. (15分) 接口与多态应用
为了模拟计算机连接不同 USB 设备的功能,请设计以下类和接口:
- (1) 定义一个接口
USB,包含两个抽象方法:void open()(开启设备) 和void close()(关闭设备)。 - (2) 定义两个实现类
Mouse(鼠标) 和Keyboard(键盘),它们都实现USB接口。Mouse的open打印 “鼠标连接”,close打印 “鼠标断开”。Keyboard的open打印 “键盘连接”,close打印 “键盘断开”。
- (3) 定义一个类
Laptop(笔记本电脑),包含一个方法public void useUSB(USB usb)。- 该方法首先调用传入设备的
open()方法。 - 进阶考点:使用
instanceof判断传入的设备类型:如果是Mouse,额外打印 “进行点击操作”;如果是Keyboard,额外打印 “进行打字操作”。 - 最后调用设备的
close()方法。
- 该方法首先调用传入设备的
- (4) 编写
main方法,实例化Laptop,并分别测试插入Mouse和Keyboard对象。
3. (15分) IO 流与文件处理
编写一个 Java 程序实现简单的文件内容拷贝与处理功能:
- (1) 程序需要读取当前目录下名为
source.txt的文本文件(假设文件已存在)。 - (2) 使用字符流(如
FileReader/BufferedReader)逐行读取文件内容。 - (3) 将读取到的每一行内容转换成大写字母 (UpperCase)。
- (4) 将转换后的内容写入到当前目录下的
dest.txt文件中(使用FileWriter/PrintWriter)。 - (5) 核心要求:必须使用标准的
try-catch-finally结构(或 try-with-resources)来处理 IO 异常,并确保在finally块中正确关闭输入流和输出流,防止资源泄露。
💡 模拟卷考点对标分析 (为什么这么出题?)
| 题目 | 真题考点 | 模拟卷考点 | 差异化/复习目的 |
|---|---|---|---|
| 简 1 | 值传递 vs 引用传递 | String 不可变性 + 数组引用传递 | String 是特殊的引用类型,是面试和考试的常客。 |
| 简 2 | 抽象类 vs 接口 | static 关键字详解 | static 是 Java 基础中仅次于 OOP 的核心概念。 |
| 简 3 | ArrayList vs LinkedList | HashSet vs TreeSet | 考察对 Set 体系及哈希/树结构的理解。 |
| 简 4 | final/finally | 访问修饰符 (public/private…) | 考察封装性基础,必须死记硬背的知识点。 |
| 简 5 | 线程定义方式 | sleep() vs wait() | 线程状态控制是多线程考题的另一面。 |
| 简 6 | 重载 vs 覆写 | 复杂多态/动态绑定 | 难度升级,考察引用类型与实际对象类型不一致时的调用规则。 |
| 简 7 | Map 接口特点 | Hashtable vs HashMap | 经典的“线程安全 vs 性能”对比。 |
| 简 8 | String vs StringBuilder | try-catch-return 执行顺序 | 考察 finally 的强制执行性,这是一个经典陷阱。 |
| 简 9 | 自定义异常 | 异常分类 (Checked vs Runtime) | 考察对 Java 异常体系结构的宏观理解。 |
| 简 10 | super/this 构造 | 类加载与对象初始化顺序 | 更加深入考察代码块的执行时机(考研/面试高频)。 |
| 简 11 | 线程同步问题 | 银行取款线程安全问题 | 场景变了,但核心考点依然是“读-改-写”原子性。 |
| 编 1 | 复数类 + 排序 | 学生类 + 复合排序 | 增加了“成绩相同按姓名排”的逻辑,考察 Comparator 的灵活运用。 |
| 编 2 | 接口 (体积计算) | 接口 (USB设备) + instanceof | 增加了向下转型 (Downcasting) 的考查。 |
| 编 3 | Socket + IO | 文件 IO + 异常处理 | 将网络编程替换为纯文件操作,强化流的关闭和异常处理规范。 |
没问题,这是为您单独整理的Java 期末模拟卷参考答案。
Java 期末模拟仿真卷 - 参考答案
第一部分:简答与程序分析题答案
1. String 不可变性分析
- 运行结果:
good and gbc - 解析:
- Java 中
String是不可变对象。change方法中的s是str引用的副本,s = "changed"只是将副本指向了堆中的新字符串常量,原str指向的 “good” 保持不变。 - 数组是引用类型,
c和ch指向堆中同一个数组对象,修改c[0]会直接改变原数组内容。
- Java 中
2. static 关键字
- 成员变量: 静态变量(类变量),全类共享一份,随着类的加载而创建,不依赖于对象实例。
- 成员方法: 静态方法,通过类名直接调用,不能直接访问非静态成员(因为没有
this指针)。 - 静态代码块: 在类被 JVM 加载时执行,且只执行一次,通常用于初始化静态资源(如 JDBC 驱动加载)。
3. HashSet vs TreeSet
- 选择:
HashSet。 - 原因:
HashSet底层是哈希表,插入和查找的时间复杂度接近 $O(1)$,效率极高。TreeSet底层是红黑树,虽然能排序,但时间复杂度为 $O(\log n)$,效率不如 HashSet。- 题目明确说明“不要求顺序”,因此追求性能选
HashSet。
4. 访问权限修饰符
- private: 仅本类可见。
- default (不写): 本类 + 同包可见。
- protected: 本类 + 同包 + 不同包的子类可见。
- public: 所有类可见。
5. sleep() vs wait()
- 区别:
sleep():Thread类的静态方法,让线程暂停执行,不会释放锁。wait():Object类的方法,必须在同步代码块/方法中调用,让线程暂停,会释放锁。
- 能否继承 Thread: 不能。
- 原因: Java 是单继承机制。如果类已经实现了
Runnable接口,它通常是为了解决已经继承了其他父类的问题。如果该类已经继承了别的父类,就无法再继承Thread类。
- 原因: Java 是单继承机制。如果类已经实现了
6. 多态分析
- 运行结果:
- ①
A and A - ②
B and A
- ①
- 解析:
- 引用变量类型决定了编译时能调用哪些方法(只能调用 A 类有的方法)。
- 实际对象类型决定了运行时执行哪个版本的方法(如果子类覆写了,执行子类的)。
a1.show(b):A 类中没有show(B),只有show(A)。B 是 A 的子类,所以匹配show(A)。a2.show(b):a2是 B 的实例。B 类覆写了show(A)。所以调用 B 类的show(A)方法,输出B and A。
7. Hashtable vs HashMap
- 线程安全: Hashtable 是线程安全的(方法有 synchronized),HashMap 不是。
- Null 值: Hashtable 的键和值都不允许 null;HashMap 允许一个 null 键和多个 null 值。
- 效率: HashMap 效率高于 Hashtable(因为没有同步锁的开销)。
8. try-catch-finally 执行顺序
- 运行结果:
finally run, result=1 - 解析:
try块中的return x执行时,会将x的值(1)暂存在栈中准备返回。- 程序必须先执行
finally块,此时x变为 2。 finally执行完毕后,方法真正返回,返回的是之前暂存的值(1),而不是修改后的 2。
9. 异常类型区别
- 受检异常 (Checked Exception): 编译器强制要求处理(try-catch 或 throws),通常是外部错误。
- 例子:
IOException,SQLException,ClassNotFoundException。
- 例子:
- 运行时异常 (Runtime Exception): 编译器不强制处理,通常是编程逻辑错误。
- 例子:
NullPointerException,IndexOutOfBoundsException,ArithmeticException。
- 例子:
10. 初始化顺序
- 运行结果:
Base Static, Sub Static, Base Const, Sub Block, Sub Const - 顺序规则:
- 父类静态代码块
- 子类静态代码块
- 父类构造方法
- 子类构造代码块
- 子类构造方法
11. 线程安全分析
- 问题: 存在线程安全问题(竞态条件)。多个线程可能同时通过
if(balance >= amount)判断,导致余额扣减成负数。 - 修改方案: 在方法上添加
synchronized关键字。1
2
3
4
5
6public synchronized void withdraw(int amount) {
if (balance >= amount) {
try { Thread.sleep(10); } catch (Exception e) {}
balance = balance - amount;
}
}
第二部分:编程题参考代码
1. 集合与排序 (Comparator)
1 | import java.util.*; |
2. 接口与多态 (instanceof)
1 | // 1. 接口 |
3. IO 流与异常处理 (Try-with-Resources)
1 | import java.io.*; |
