很多时候我们需要保存/读取对象的状态或者在进程之间传输对象的需求。比如将对象数据存储到数据库,从数据库读取数据到程序实例化为对象、web服务中的session数据持久化到缓存中,以及在不同进程或者不同程序之间传输对象。而对象的存储和传输都是以二进制形式进行的,所以如果我们要存储或者传输对象需要将对象保存为二进制的形式进行存储。
序列化就是解决对象转换为字节序列的问题的,而反序列化正好相反就是把二进制数据转换为对象数据。
1.概念
1.1序列化
把对象转换为字节序列的过程就是序列化。
1.2.反序列化
把字节序列转换为对象的过程就是反序列化。
2.序列化的用途
2.1.对象的字节序列永久的存储到硬盘上
比如数据库存放数据的过程,以及session存储到硬盘上的过程。
2.2.在网络上传输对象的字节序列
比如分布式系统中的对象传输。
2.3.当你想通过 RMI 传输对象的时候;
3.Jdk中的序列化
3.1.被序列化对象要实现Serializable接口或者Externalizable
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
3.1.1.serialVersionUID生成
这个字段表面的意思是序列化的版本号,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量,类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。
3.1.1.serialVersionUID作用
1.版本兼容
在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID。
2.版本不兼容
在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
3.2.序列化/反序列化的相关流
3.2.1.ObjectOutputStream
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
3.2.1.ObjectInputStream
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
3.3.对象序列化/反序列化步骤:
3.3.1.序列化
- 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
- 通过对象输出流的writeObject()方法写对象。
3.3.2.反序列化
- 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 通过对象输入流的readObject()方法读取对象。
4.序列化反序列化的例子
实体类:
package com.dada.foo;
import java.io.Serializable;
/**
* @author ztd
*
*/
public class MyFoo1 implements Serializable {
private static final long serialVersionUID = 1;
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public MyFoo1(int width, int height) {
super();
this.width = width;
this.height = height;
}
}
测试类:
@Test
public void testWriteAndReadbject() throws Exception {
MyFoo1 myFoo = new MyFoo1(20, 30);
// 把对象写到文件中
FileOutputStream fos = new FileOutputStream("D:\\myFoo.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myFoo);
// 读取对象信息
FileInputStream fis = new FileInputStream("D:\\myFoo.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
MyFoo1 myFoo1 = (MyFoo1) ois.readObject();
}
简而言之:java序列化的作用就是为了不同jvm之间共享实例对象的一种解决方案.由java提供此机制,效率之高,是其他解决方案无法比拟的。