1. 序列化和反序列化
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
2. Serializable接口是什么
这是对象序列化接口,一个类只有实现了Serializable接口,它的对象才能被序列化。
Serializable接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可。
3. 什么情况下需要序列化
当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化
4. 测试
将java对象序列化并持久保存在文件中,再从文件中反序列化为对象的测试过程。
4.1 创建一个普通实体类(People)
4.2 创建一个测试用序列化工具类(SerializableTools )
/**
* 测试Serializable接口作用
*
* 1.在对没有实现Serializable接口,进行写入文件操作时会出现异常:java.io.NotSerializableException
* 2.正常情况下:无论有无serialVersionUID字段,都不影响对象的序列化和反序列化,因为用户没有定义该字段时,jvm会自动创建一个值
* 3.在没有定义serialVersionUID时,当已经对现在的对象进行了序列号存储,如果用户改变了类的变量个数、变量类型等情况会导致数据反序列化失败抛出异常:
* java.io.InvalidClassException:local class incompatible: stream classdesc serialVersionUID = -1914612148418344721, local class serialVersionUID = -8347405390320853159
* 4.如果用户有自定义serialVersionUID字段的值,便不会出现第3点的情况,所以建议用户自定义serialVersionUID字段的值。
*/
public class SerializableTools {
public static void main(String[] args) throws IOException {
File file = new File("./common/src/main/java/com/study/serializable/test.txt");
People people = new People();
people.setId(1);
people.setName("新风");
people.setAge(23);
System.out.println("序列化对象:"+people.toString());
writeToFile(people,file);
People p = readFromFile(file);
System.out.println("反序列化结果:"+p.toString());
}
private static void writeToFile(People people, File file) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(people);
}
private static People readFromFile(File file) throws IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
People p = null;
try {
p = (People) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return p;
}
}
4.3 测试过程
4.3.1 正常运行程序没有问题,运行结果:
4.3.2 People
去掉implements Serializable
,运行程序时抛出异常:java.io.NotSerializableException
,所以在对没有实现Serializable
接口,进行写入文件操作时会出现异常,序列化失败。
4.3.3 还原上面的代码,分别运行注释掉People
类中的第16行
,和不注释结果都没有问题。所以正常情况下:无论有无serialVersionUID
字段,都不影响对象的序列化和反序列化,因为用户没有定义该字段时,jvm会自动创建一个值。
4.3.4 先还原代码,然后注释掉People
类的第16行和22行
,运行程序将people序列化到test.txt中,然后取消People
类的第22行
注释并注释SerializableTools
类的第15-20行
,再次运行程序则抛出异常: java.io.InvalidClassException:local class incompatible: stream classdesc serialVersionUID = -1914612148418344721, local class serialVersionUID = -8347405390320853159
,所以,在没有定义serialVersionUID
字段时,当已经对现在的对象进行了序列号存储,如果用户改变了类的变量个数、变量类型等情况会导致数据反序列化失败抛出异常。
4.3.5 还原代码,重复4.3.4的操作,但整个过程中不
对People
类的第16行
注释,程序正常运行,这个过程中两次运行,相当于sex
字段是新增字段,反序列化结果sex
的值为null
,所以建议用户自定义serialVersionUID
字段的值。