JAVA 序列化、反序列化以及 serialVersionUID
public void setAge(Integer age) {
this.age = age;
}
}
可以看到上面的类 Dog 实现了 Serializable, 标记这个类是可以序列化的。
有人也注意到了,为什么没有弄 serialVersionUID ??
其实咱们如果不手动设置 serialVersionUID,会有默认计算出的 serialVersionUID 的。后面再讨论为什么有手动弄 serialVersionUID 的场景。
结合代码
序列化
import com.jc.mytest.model.Dog;
import java.io.*;
/**
@Author : JCccc
@CreateTime : 2020/4/21
@Description :
**/
public class SerializeTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化对象-IO 流-存储
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\dogInfoText.out"));
Dog dog=new Dog();
dog.setName("阿福");
dog.setAge(1);
objectOutputStream.writeObject(dog);
objectOutputStream.flush();
objectOutputStream.close();
}
}
运行一下,可以看到我们的 D 盘生成了这个 Dog 类型序列化后的文件,

里面全是 ‘乱码’,没事乱码我们看不懂,但是 jvm 能看懂。

反序列化
public class SerializeTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\dogInfoText.out"));
Dog dog = (Dog) objectInputStream.readObject();
System.out.println("dog's name:"+dog.getName());
}
}
运行结果,跟我们序列化进去的 Dog 设置的字段属性值一样:

序列化和反序列化的简单使用操作已经完毕,作用显然都知道了,简单的理解就是转存为字节流可以方便传输,然后反序列化可以快速地拿到原来的对象。
那么接下来我们来看看为什么要加?serialVersionUID ? 如:
private static final long serialVersionUID = -8567374045705746827L;
private static final long serialVersionUID = 1L;
上面有说过如果我们不手动加这个?serialVersionUID,是会默认生成一个的,只是我们看不到。
上面也有说过,这个 serialVersionUID 就像是这个类的身份证号码一样,具有唯一识别的性质。
举例:
原本我们的 Dog 类只有 2 个字段属性,

然后我们进行了序列化, 这时候,对应默认对应的?serialVersionUID,绑定的内容是这个 Dog,有 2 个字段属性,
已经序列化保存到 D:\\dogInfoText.out 文件里面了。
这时候我们进行一个修改,增加一个字段,nickName 。如:

此时,我们进行反序列化的操作,就会报错:

因为系统默认给之前序列化的 Dog 是生成了一个 serialVersionUID 的,里面绑定的属性只有两个,现在你让三个属性的去接收反序列化后的 Dog 类,且身份证号码不一样,肯定报错了。
这时候避免这种情况的出现,手动设置一个 serialVersionUID 就可以,如:

加上 serialVersionUID 之后的 Dog,序列化之后,无论后面怎么修改,只要 serialVersionUID 不变,反序列化就可以正常进行。
评论