🍑什么是序列化
当我们执行程序需要多个对象数据的时候, 每次执行程序都有重新创建赋值, 很消耗资源, 可以将对象的完整信息保存在文件中, 之后可以使用反序列化从文件中将对象读取出来
序列化流
ObjectOutputStream(OutputStream os): 负责将对象序列化, 并不具备写文件的功能
反序列化流
ObjectInputStream(InputStream is) : 负责将对象反序列化, 并不具备读文件的功能
🍑单个对象的序列化和反序列化
序列化:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SeriableDemo {
public static void main(String[] args) throws Exception{
//person类要实现Serializable接口
Person person = new Person("马思纯",18);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("io\\序列化.txt"));
oos.writeObject(person);
oos.close();
}
}
反序列化:
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class SerializableDemo2 {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("io\\序列化.txt")));
Person p = (Person) ois.readObject();
System.out.println(p);
}
}
🍑多个对象的序列化和反序列化
不建议将对象一个一个序列化, 反序列化读取时没有末尾的结束标记, 一旦读取到末尾就报异常, 因此不能使用循环读取, 导致操作不方便
建议将对象存入ArrayList集合中, 序列化和反序列化只针对一个数组进行操作
序列化:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
public class SeriableDemo3 {
public static void main(String[] args) throws Exception{
//person类要实现Serializable接口
Person person1 = new Person("马思纯",18);
Person person2 = new Person("倪妮",18);
Person person3 = new Person("杨幂",18);
ArrayList<Person> personList = new ArrayList<>();
Collections.addAll(personList,person1,person2,person3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("io\\序列化.txt"));
oos.writeObject(personList);
oos.close();
}
}
反序列化:
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class SerializableDemo2 {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("io\\序列化.txt")));
ArrayList<Person> list = (ArrayList<Person>) ois.readObject();
list.forEach(System.out::println);
}
}
🍑序列化的serialVersionUID标记
序列化后 反序列化前对类做了内容上的更改, 会报错: 无效类异常
serialVersionUID是实现序列化的类通过组成部分, 计算出long类型身份id(隐式).
一旦更改组成部分,相当于给类更换了新的UID, 反序列化就不能通过序列化时的serialVersionUID找到类 , 文件出来的字节序列就不能反序列化成类对象
解决方式:
保证类的serialVersionUID值不更改
类中不定义会系统默认生成serialVersionUID值, 如果在类中自己显示生成, 就使用自己定义的值保存
1. 自己定义private static final serialVersionUID = 123456L;
2. 使用IDEA快捷生成一个UID
🍑使用瞬态关键字脱敏
某个字段的值不想被序列化到文件中,使用瞬态关键字transient
eg: 对象("张三",18) 对年龄使用瞬态关键字, 真正序列到文件中的只有"张三". 反序列化回来的时候, 年龄字段是默认值
🍑总结
1. 想要被序列化的类需要实现可序列化的接口 Serilizable
2. 完成序列化或者反序列化后 要将资源关闭
3. 最好自定义类的serialVersionUID
4. 对敏感字段数据可以选择使用瞬态关键字transient
反序列化读取时没有末尾的结束标记, 一旦读取到末尾就报异常, 因此不能使用循环读取
序列化后 反序列化前对类的组成部分做了更改, 导致serialVersionUID不一致, 会报错: 无效类异常