序列化与反序列化
一、是什么
-
序列化:就是将对象转化成字节序列(byte[]数组)的过程。
-
反序列化:就是讲字节序列转化成对象的过程。
二、为什么
那么为什么要去进行序列化呢?主要有以下两个原因:
- 持久化:对象是存储在JVM中的堆区的,但是如果JVM停止运行了,对象也不存在了。序列化可以将对象转化成字节序列,可以写进硬盘文件中实现持久化。读取时再反序列化得到对象数据
- 网络传输:网络直接传输数据,但是无法直接传输对象,可在传输前序列化为字节序列,传输完成后反序列化成对象。
三、怎么做
怎么去实现对象的序列化呢?
- 对于要序列化对象的类要去实现Serializable接口
- 实现方法:JDK提供的ObjectOutputStream和ObjectInputStream来实现序列化和反序列化
下面用Serializable接口来演示序列化和反序列化
测试类:
public class TestBean implements Serializable {
private Integer id;
private String name;
private Person per;
}
序列化:
public static void main(String[] args) {
TestBean testBean = new TestBean();
testBean.setId(1435);
testBean.setName("ergf方式");
testBean.setPer(new Person());
//使用ObjectOutputStream序列化testBean对象并将其序列化成的字节序列写入test.txt文件
try {
FileOutputStream fileOutputStream = new FileOutputStream("D:\\test.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(testBean);
} catch (IOException e) {
e.printStackTrace();
}
}
反序列化:
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("D:\\test.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
TestBean testBean = (TestBean) objectInputStream.readObject();
System.out.println(testBean);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
需要注意的问题:
-
如果一个可序列化的类的成员包括引用类型的,那这个引用类型也必须是可序列化的;否则,会导致此类不能序列化。(比如上面例子中TestBean类的per成员,它的Person也必须是可序列化的)
-
同一个对象多次序列化成多个字节序列,这多个字节序列反序列化成的对象还是同一个(使用==判断为true)(因为所有序列化保存的对象都会生成一个序列化编号,当再次序列化时回去检查此对象是否已经序列化了,如果是,那序列化只会输出上个序列化的编号)
-
transient关键字:对于不想序列化的字段可以再字段类型之前加上
transient关键字修饰(反序列化时会被赋予默认值)。静态变量不管是否被transient修饰,均不能被序列化。