什么是序列化和反序列化
**序列化:**指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。这个过程称为序列化。通俗来说就是将数据结构或对象转换成二进制串的过程
**反序列化:**把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。也就是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
什么时候需要序列
- 在分布式系统中,此时需要把对象在网络上传输,就得把对象数据转换为二进制形式,需要共享的数据的 JavaBean 对象,都得做序列化
- 服务器钝化:如果服务器发现某些对象好久没活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化我们的对象数据,恢复成 Java 对象。这样能节省服务器内存
如何实现序列化
- 需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口(这是一个标志接口,没有任何抽象方法),Java 中大多数类都实现了该接口,比如:String,Integer
- 底层会判断,如果当前对象是 Serializable 的实例,才允许做序列化,Java对象 instanceof Serializable 来判断。
- 在 Java 中使用对象流来完成序列化和反序列化,
ObjectOutputStream:通过 **writeObject()**方法做序列化操作
ObjectInputStream:通过 readObject() 方法做反序列化操作
一般情况下,类实现了Serializable 接口后,要手动的添加一个序列化版本号字段:
公共类person类 测试序列化和反序列化
import java.io.Serializable;
/**
* 描述:person类 测试序列化和反序列化
*/
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
}
对象序列化流: ObjectOutputStream
将Java对象的原始数据类型和图形写入OutputStream, 可以使用ObjectlnputStream读取 (重构)对象。可以通过使用流的文件来实现对象的特久存储。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
ObjectOutputStream(OutputStreamout):创建一个写入指定的Outputstrearm的ObjectOutputStrearm序列化对象的方法
void writeObject(Object obj): 将指定的对象写入ObjectOutputStream
序列化测试类代码如下:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* 描述:把Person类进行序列化
*/
public class Test {
public static void main(String[] args) throws Exception {
serializePerson();
}
/**
* 序列化
*/
private static void serializePerson() throws IOException {
Person person = new Person("123");
// ObjectOutputStream 对象输出流
// person.txt 文件中,完成对 person 对象的序列化操作
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("test01\\person.txt")));
oos.writeObject(person);
System.out.println("person 对象序列化成功!");
oos.close();
}
}
对象反序列化流: ObjectinputStream
使用ObjectnputStream进行反字列化,简单的理解为把文件中的对象读取出来
反序列化对象的方法:
ObjectreadObject(): 从ObjectnputStream读取 一个对象
进行反序列化测试代码:
import java.io.*;
/**
* 描述:进行反序列化
*/
public class Test {
public static void main(String[] args) throws Exception {
Person person = deserializePerson();
System.out.println(person.toString());
}
/**
* 反序列化
*/
private static Person deserializePerson() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("e:/person.txt")));
Person person = (Person) ois.readObject();
System.out.println("person 对象反序列化成功!");
return person;
}
}
总结
- 一个类如果想被序列化,那么需要实现一个Serializable接口
- 类中的静态变量的值是不会被进行序列化的,transient 修饰的属性,是不会被序列化的,内置类型 为对应0值。引用类型为null; 用transient关键字标记的成员变量不参与序列化过程
- 在实现这个Serializable 接口的时候,一定要给这个 serialVersionUID 赋值,最好设置为1L,这 个L最好大写来区分,不然小写看起来像是1,不同的 serialVersionUID 的值,会影响到反序列化