一 简介
把对象转换为字节序列的过程称为对象的序列化
把字节序列恢复为对象的过程称为对象的反序列化
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
二 Java中的序列化API
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中;java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回
只有实现了Serializable或Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
对象序列化包括如下步骤:
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
2) 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
2) 通过对象输入流的readObject()方法读取对象。
三 使用Serializable接口实现的实例
首先定义了一个实现了Serializable接口WebSite的实体类
package cn.zifangsky.serializable;
import java.io.Serializable;
public class WebSite implements Serializable {
private static final long serialVersionUID = 1835573222135484360L;
private String siteName;
private String siteUrl;
private String webMaster;
public WebSite() {
}
public WebSite(String siteName, String siteUrl, String webMaster) {
this.siteName = siteName;
this.siteUrl = siteUrl;
this.webMaster = webMaster;
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
}
public String getSiteUrl() {
return siteUrl;
}
public void setSiteUrl(String siteUrl) {
this.siteUrl = siteUrl;
}
public String getWebMaster() {
return webMaster;
}
public void setWebMaster(String webMaster) {
this.webMaster = webMaster;
}
public String toString() {
return "WebSite [siteName=" + siteName + ", siteUrl=" + siteUrl + ", webMaster=" + webMaster + "]";
}
}然后进行序列化和反序列化测试:
package cn.zifangsky.serializable;
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;
public class TestSerialize {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
TestSerialize.serializeWebSite();
TestSerialize.deserializeWebSite();
}
/**
* 使用ObjectOutputStream 序列化WebSite
* @throws IOException
* @throws FileNotFoundException
*
* */
public static void serializeWebSite() throws FileNotFoundException, IOException{
WebSite webSite = new WebSite();
webSite.setSiteName("zifangsky的个人博客");
webSite.setSiteUrl("http://www.zifangsky.cn");
webSite.setWebMaster("zifangsky");
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/Administrator/Desktop/test.txt")));
objectOutputStream.writeObject(webSite);
objectOutputStream.flush();
objectOutputStream.close();
}
/**
* 使用ObjectInputStream 反序列化WebSite
* @throws IOException
* @throws FileNotFoundException
* @throws ClassNotFoundException
*
* */
public static void deserializeWebSite() throws FileNotFoundException, IOException, ClassNotFoundException{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("C:/Users/Administrator/Desktop/test.txt")));
//反序列化
WebSite webSite = (WebSite) objectInputStream.readObject();
objectInputStream.close();
System.out.println(webSite);
}
}输出:
WebSite [siteName=zifangsky的个人博客, siteUrl=http://www.zifangsky.cn, webMaster=zifangsky]
四 使用Externalizable接口实现的实例
实现了Externalizable接口的实体类:
package cn.zifangsky.serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class ExternalizableDemo implements Externalizable{
private String name;
static {
System.out.println("调用静态代码块");
}
public ExternalizableDemo() {
System.out.println("调用无参构造方法");
}
public ExternalizableDemo(String name) {
this.name = name;
System.out.println("调用有参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "ExternalizableDemo [name=" + name + "]";
}
/**
* ObjectOutputStream会调用writeExternal(ObjectOutput out))这个方法进行序列化
* */
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
}
/**
* ObjectInputStream会调用readExternal(ObjectInput in)这个方法进行反序列化
* */
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
}
}然后进行序列化和反序列化测试:
package cn.zifangsky.serializable;
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;
public class TestExternalizable {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
ExternalizableDemo demo = new ExternalizableDemo("hello");
// 序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
new FileOutputStream(new File("C:/Users/Administrator/Desktop/test2.txt")));
objectOutputStream.writeObject(demo);
objectOutputStream.flush();
objectOutputStream.close();
//反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("C:/Users/Administrator/Desktop/test2.txt")));
ExternalizableDemo demo2 = (ExternalizableDemo) objectInputStream.readObject();
objectInputStream.close();
System.out.println(demo2);
}
}输出:
调用静态代码块 调用有参构造方法 调用无参构造方法 ExternalizableDemo [name=hello]
注:
(1)使用Externalizable进行序列化时,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中
(2)Externalizable接口继承自Serializable接口。两者的区别如下:
假设有一个Customer类的对象需要序列化,如果这个类仅仅实现了这个接口,那么序列化和反序列化的方式如下:ObjectOutputStream采用默认的序列化方式,对于这个类的非static,非transient的实例变量进行序列化,ObjectInputStream采用默认的反序列化方式,对于这个类的非static,非transient的实例变量进行反序列化。
如果这个类不仅实现了Serializable接口,而且定义了readObject(ObjectInputStream in)和 writeObject(ObjectOutputStream out)方法,那么将按照如下的方式进行序列化和反序列化:
ObjectOutputStream会调用这个类的writeObject方法进行序列化,
ObjectInputStream会调用相应的readObject方法进行反序列化。
实现Externalizable接口的类完全由自身来控制序列化的行为。而且必须实现writeExternal(ObjectOutput out)和readExternal(ObjectInput in)。那么将按照如下的方式进行序列化和反序列化:
ObjectOutputStream会调用这个类的writeExternal方法进行序列化,
ObjectInputStream会调用相应的readExternal方法进行反序列化。
PS:
如果想要进一步了解,可以参考这篇文章:http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html
参考文章:
(1)http://www.cnblogs.com/xdp-gacl/p/3777987.html
(2)http://www.cnblogs.com/rollenholt/archive/2012/11/26/2789445.html
本文出自 “zifangsky的个人博客” 博客,请务必保留此出处http://983836259.blog.51cto.com/7311475/1758247
原文地址:http://983836259.blog.51cto.com/7311475/1758247