序列化流和反序列化流

序列化流/对象操作输出流ObjectOutputStream
构造方法
| 构造方法 | 说明 |
|---|
| public ObjectOutputStream(OutputStream out) | 把基本流包装成高级流 |
成员方法
| 成员方法 | 说明 |
|---|
| public final void writeObject(Object obj) | 把对象序列化(写出)到文件中 |
- 细节
- 使用对象输出流将对象保存到文件中会出现NotSerializableException异常
- 解决方案:需要让JavaBean类实现Serializable接口
- Serializable接口中是没有抽象方法的,是标记型接口,一旦实现了这个接口,那么就表示当前的JavaBean类是可以被序列化的
使用
Student stu = new Student("张三", 18);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(...));
oos.writeObject(stu);
oos.close();
反序列化流/对象操作输入流ObjectInputStream
构造方法
| 构造方法 | 说明 |
|---|
| public ObjectInputStream(InputStream in) | 把基本流变成高级流 |
成员方法
| 成员方法 | 说明 |
|---|
| public Object readObject() | 把序列化到本地文件中的对象,读取到程序中来 |
使用
ObjectInputStream ois = new ObjectInputStream(new FileInputStream());
Student o = (Student) ois.readObject();
ois.close();
使用细节
-
使用序列化流将对象写到文件时,需要让JavaBean类实现Serializable接口,否则,会出现NotSerializableException异常
-
序列化流写到文件中的数据是不能更改的,一旦修改就无法再次读回来了
-
当我们更改了JavaBean类后,再将文件中的对象读取到程序中时,会抛出InvalidClassException异常
- 原因:如果一个JavaBean类实现了Serializable接口,说明这个对象是可被序列化的,此时Java底层会根据类中的所有数据进行计算,得到一个long类型的版本号,将对象写入到文件中是也会把版本号写入文件中,如果更改了JavaBean类,对应的版本号也会改变,此时再将文件中的对象读取到程序中时,两者的版本号不匹配,报错
- 解决方案1:在JavaBean类中手动定义一个永远都不会更改的版本号
- 解决方案2:对IDEA进行手动设置,在Settings中搜索Serializable,勾选
Non-serializable class with 'serialVersionUID' 和 Transient field is not initialized on deserialization 选项
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
}
- 如果不想将某些属性序列化到文件中,可以在属性定义前加入transient关键字,该关键字标记的成员变量不参与序列化过程
- transient关键字:瞬态关键字
- 作用:不会将当前属性序列化到本地文件中
private transient String address;
读写多个对象
- 将多个自定义对象序列化读到文件中,但是由于对象的个数不确定,反序列化流该如何读取呢?
- 一般将先将多个对象先存入到集合中,将集合写入到文件中
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 19);
Student s3 = new Student("王五", 20);
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectOutStream oos = new ObjectOutStream(FileInputStream("..."));
oos.writeObject(list);
oos.close;
ObjectInputStream ois = new ObjectInputStream(FileInputStream("..."));
ArrayList<Student> list = (ArrayLiat<Student>) ois.readObject();
for (Student stu : list) {
System.out.println(stu);
}
ois.close();