Java 对象序列化实战解析:对象的持久化存储与读取
一、原题完整代码呈现
以下是计算机二级Java考试中关于对象序列化的典型题型,主要考察对象输入输出流的使用、序列化接口的实现以及对象字符串表示,包含4处需要填写的空白(标记为//*********Found**********
):
import java.io.*;
public class Java_2 {
public static void main(String[] args) {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
File f = new File("Person.dat");
//*********Found**********
oos = new ObjectOutputStream(new _____________________(f));
oos.writeObject(new Person("小王"));
oos.close();
ois = new ObjectInputStream(new FileInputStream(f));
//*********Found**********
Person d = (Person) ois._____________();
System.out.println(d);
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//*********Found**********
class Person implements __________________ {
String name = null;
public Person(String s) {
name = s;
}
//*********Found**********
public String _____________() {
return name;
}
}
二、空白处逐一解析与解答
1. 第一处空白:创建文件输出流
答案:FileOutputStream
//*********Found**********
oos = new ObjectOutputStream(new FileOutputStream(f));
解析: ObjectOutputStream
用于将对象序列化到输出流,其构造方法需要接收一个字节输出流。FileOutputStream(f)
创建文件输出流,将数据写入Person.dat
文件,因此填写FileOutputStream
,作为ObjectOutputStream
的底层输出流。
2. 第二处空白:读取序列化对象
答案:readObject
//*********Found**********
Person d = (Person) ois.readObject();
解析: ObjectInputStream
的readObject()
方法用于从输入流中读取序列化的对象,返回值为Object
类型,需要强制转换为Person
类型。此处通过该方法恢复之前序列化的Person
对象,因此填写readObject
。
3. 第三处空白:实现序列化接口
答案:Serializable
//*********Found**********
class Person implements Serializable {
解析:
要使对象可序列化,其所属类必须实现java.io.Serializable
接口(标记接口,无方法需要实现)。Person
类的对象需要被序列化到文件,因此必须实现该接口,填写Serializable
。
4. 第四处空白:重写字符串表示方法
答案:toString
//*********Found**********
public String toString() {
return name;
}
解析: System.out.println(d)
打印对象时,会调用toString()
方法。为了输出Person
对象的姓名(而非默认的类名+哈希码),需要重写toString()
方法返回name
,因此填写toString
。
三、完整正确代码
四、程序功能与运行说明
程序功能
该程序实现对象的序列化与反序列化(持久化),核心功能包括:
- 定义
Person
类(实现Serializable
接口),用于存储姓名信息 - 将
Person
对象序列化(写入)到Person.dat
文件 - 从
Person.dat
文件反序列化(读取)Person
对象 - 打印反序列化得到的对象信息
运行说明
程序执行流程:
- 创建
Person.dat
文件(若不存在) - 通过
ObjectOutputStream
将Person("小王")
对象序列化到文件 - 关闭输出流后,通过
ObjectInputStream
从文件读取对象 - 反序列化得到
Person
对象并打印其姓名
- 创建
- 运行结果:控制台输出
小王
- 副作用:当前目录下生成
Person.dat
文件(二进制格式,存储序列化数据)
五、核心知识点总结
对象序列化的基本概念
- 定义:将对象的状态转换为字节流,以便存储或传输的过程(序列化);反之称为反序列化
核心类:
ObjectOutputStream
:提供writeObject(Object obj)
方法实现序列化ObjectInputStream
:提供readObject()
方法实现反序列化
- 底层流:必须基于字节流(如
FileOutputStream
/FileInputStream
)构建
Serializable接口的作用
- 标记接口:
Serializable
接口没有任何方法,仅作为标记表示该类的对象可被序列化 - 必须实现:若类未实现该接口,调用
writeObject()
会抛出NotSerializableException
- 版本控制:可通过
serialVersionUID
常量指定序列化版本,确保反序列化兼容性(如private static final long serialVersionUID = 1L;
)
- 标记接口:
序列化的操作步骤
- 创建底层文件流(
FileOutputStream
/FileInputStream
) - 构建对象流(
ObjectOutputStream
/ObjectInputStream
)包装底层流 - 序列化:
oos.writeObject(obj)
将对象写入流 - 反序列化:
ois.readObject()
从流读取对象(需强制类型转换) - 关闭流:使用后关闭对象流,释放资源
- 创建底层文件流(
toString()方法的意义
- 打印对象时,
System.out.println(obj)
会自动调用obj.toString()
- 默认实现:
Object
类的toString()
返回类名@哈希码
(如Person@1b6d3586
) - 重写目的:返回有意义的字符串表示(如
Person
类的姓名),便于调试和输出
- 打印对象时,
六、常见错误与应试技巧
常见错误分析
- 第一处空白流类型错误:使用
FileWriter
(字符流)而非FileOutputStream
(字节流),对象流必须基于字节流 - 第二处空白方法名错误:写成
read()
或readObject()
遗漏括号,正确方法是readObject()
- 第三处空白接口名错误:写成
Serializable()
(加括号)或serializable
(小写),接口名是Serializable
- 第四处空白方法名错误:写成
toString
遗漏括号,或写成getname
(与打印逻辑不符)
- 第一处空白流类型错误:使用
应试技巧
- 序列化口诀:"对象要持久,必须序列化;接口Serializable,流用ObjectXxx;写用writeObject,读用readObject;强制转换别忘记"
- 流的嵌套关系:"对象流包装字节流,底层操作文件流"
- 调试技巧:序列化后检查文件是否生成,反序列化后验证对象属性是否正确恢复
通过本题,我们掌握了对象序列化的基本原理、实现步骤以及Serializable
接口的作用。对象序列化在分布式系统、缓存机制、会话管理等场景中广泛应用,是Java中实现对象持久化和跨网络传输的核心技术。理解序列化机制,对处理复杂对象的存储与传输具有重要意义。