前言:杜绝八股取士,活学活用从我做起,本文将会从简单的维度入手,分析序列化到底是什么?为什么要用?怎么用?有什么坑?希望能帮助到更多学习道路上的同学
1:是什么?
简单来说,序列化就是把内存中的对象通过一定的规则转换成字节序列,然后保存到磁盘,反序列化就是从磁盘中读取对应的字节序列出来恢复成原来那个对象,也可以说是根据字节序列“创建”出原来那个对象,我们都记得创建对象的几种方式:new,clone,reflect,序列化与反序列化。
2:为什么要用?
首先很明显就是保存某个对象在某一时期的某种状态,又或者为了保存某个对象的信息,你把它序列化后,可以保存在mysql数据库,也可以通过Socket进行传输,也可以保存到txt文件中,反正随便放,到时候读取出来再反序列化就可以,好处就是节约内存,如果有大量的对象,不能丢弃回收内存,但是内存空间又不足,这个时候可以考虑把一部分序列化保存到磁盘上,要用的时候再通过反序列化找回来。
3:怎么用?
(1)定义一个Student类
public class Student implements Serializable {
private static final long serialVersionUID = -5809782578272943999L;
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
(2)创建序列化的main方法
public static void main(String[] args) throws IOException {
/*创建student对象,设置姓名和年龄*/
Student student = new Student();
student.setAge(19);
student.setName("jojo");
/*通过writeObject序列化*/
ObjectOutputStream outputStream = new ObjectOutputStream(
new FileOutputStream(new File("D:\\Git\\demo\\src\\main\\java\\com\\jojo\\service\\Student.txt")));
outputStream.writeObject(student);
System.out.println("对象序列化成功!");
outputStream.close();
}
(3)执行结果
(4)查看序列化文件(也就是保存在磁盘上的对象长什么样)
(5)在另外一个main方法中通过读取该文件反序列化拿到当时的对象状态
public static void main(String[] args) throws Exception {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(
new File("D:\\Git\\demo\\src\\main\\java\\com\\jojo\\service\\Student.txt")));
Student student = (Student) inputStream.readObject();
System.out.println("age:"+student.getAge());
}
成功~!
4:有什么坑?
(1) 静态变量不能被序列化?
假设年龄我设置为static的,并且初始值为18;序列化之前我把该静态变量改成19,那么反序列化后,我拿到的是18还是19? 输出结果: 为什么呢?因为序列化是保存对象当时的状态,而静态变量属于类,所以它的改变不能被序列化保存。
(2) 静态类创建出来的对象能否序列化?
答案是可以;而且反序列后取值也正常。
为什么呢?因为还是那句话,序列化是针对对象的,关类什么事?类是一种模板,一种定义,它是不是静态跟我创建出来的对象没有半毛钱关系
(3) 静态对象能否被序列化和反序列化?
答案还是可以,为什么呢?因为,序列化的是对象,对象里面的属性只要不是静态的,就都属于该对象!是对象的东西,肯定反序列化就能拿出来啊~我又不关心该对象是否static
(4) 序列化id的作用?
SerialVersionUID它是序列化版本号,是维护序列化和反序列化的对象的版本一致的。 没加SerialVersionUID: A1对象序列化保存为A1.txt,然后A类被修改了某些属性,再通过A1.txt反序列化回来的时候就会反序列化失败。
Exception in thread "main" java.io.InvalidClassException: com.jojo.service.JoJoTest$Student; local class incompatible: stream classdesc serialVersionUID = -5809782578272943999, local class serialVersionUID = 5647668197525336519
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
at com.jojo.service.JoJoTest.main(JoJoTest.java:9)
如果加了序列号id,不管你对它属性做了什么修改,反序列化都会成功~!
目前先记录到这里,后续会持续补充~~~欢迎有其它新发现的小伙伴留言沟通交流~
|