序列化简介
序列化
- 将对象写入IO流中(把Java对象转换为字节序列的过程)
反序列化
- 从IO流中恢复对象(把字节序列恢复为Java对象的过程)
为什么要用序列化和反序列化
- 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。
详细解释
- 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
- 只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
意义
- 序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
使用场景
- 所有可在网络上传输的对象都必须是可序列化的
- 所有需要保存到磁盘的java对象都必须是可序列化的
通常建议:程序创建的每个JavaBean类都实现Serializeable接口。
如何实现Java序列化和反序列化
JDK类库中的序列化API
- java.io.ObjectOutputStream:表示对象输出流
它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。 - java.io.ObjectInputStream:表示对象输入流
它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。 - 只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
步骤
- 输出流
1.创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流
ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));
2.通过对象输出流的writeObject()方法写对象
out.writeObject(“Hello”);
out.writeObject(new Date());
- 输入流
1.创建一个对象输入流,他可以包装一个其他类型的源输入流,如文件输入流
ObjectInputStream in = new ObjectInputStream(new fileInputStream(“D:\\objectfile.obj”));
2.通过对象输入流的readObject()方法读取对象
String obj1 = (String)in.readObject();
Date obj2 = (Date)in.readObject();
示例
- 实体类
package com.mhq.question;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String sex;
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
- 测试类
package com.mhq.question;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;
public class Test {
//main函数
public static void main(String[] args) throws Exception {
SerializePerson();//序列化Person对象
Person p = DeserializePerson();//反序列Perons对象
System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
p.getName(), p.getAge(), p.getSex()));
}
//内部类
private static void SerializePerson() throws FileNotFoundException,IOException {
Person person = new Person();
person.setName("gacl");
person.setAge(25);
person.setSex("男");
// ObjectOutputStream 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操作
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
new File("D://java//Person.txt")));
oos.writeObject(person);
System.out.println("Person对象序列化成功!");
oos.close();
}
//内部类
private static Person DeserializePerson() throws Exception, IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("D://java//Person.txt")));
Person person = (Person) ois.readObject();
System.out.println("Person对象反序列化成功!");
return person;
}
}
执行结果
序列化后的结果