href="file:///C:/DOCUME~1/others/LOCALS~1/Temp/msohtml1/01/clip_filelist.xml" rel="File-List" /> href="file:///C:/DOCUME~1/others/LOCALS~1/Temp/msohtml1/01/clip_editdata.mso" rel="Edit-Time-Data" />
java 序列化及反序列化
1.概念介绍
序列化 : 将对象转化成流的过程称为序列化。
反序列化 : 将流转化成对象的过程称之为反序列化。
2.使用原则
序列化与反序列化必须遵守的原则
a) Java对象
在java中要想使一个java对象可以实现序列化与反序列化,必须让该类实现java.io.Serializable接口
java.io.Serializable接口定义如下:
publicinterface Serializable { } |
从上述定义中可以看到该接口中未定义任何方法,这大大的简化了开发者
b) 序列化主要依赖java.io.ObjectOutputStream类,该类对java.io.FileOutputStream进一步做了封装,这里主要使用ObjectOutputStream类的writeObject()方法实现序列化功能。
3.Serializable接口应用
通过下面的一段代码进行分析:
package serialized;
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.io.Serializable;
import java.util.Date;
public class SampleSerialize implements Serializable{
private int id;
private String name;
private boolean isboy;
private Date birthday;
/**
* @param id
* @param name
* @param isboy
* @param birthday
*/
public SampleSerialize(int id, String name, boolean isboy, Date birthday) {
super();
this.id = id;
this.name = name;
this.isboy = isboy;
this.birthday = birthday;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the isboy
*/
public boolean isIsboy() {
return isboy;
}
/**
* @param isboy the isboy to set
*/
public void setIsboy(boolean isboy) {
this.isboy = isboy;
}
/**
* @return the birthday
*/
public Date getBirthday() {
return birthday;
}
/**
* @param birthday the birthday to set
*/
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
//输出
public void printInfo() {
System.out.println("id : " + this.id);
System.out.println("name : " + this.name);
System.out.println("isboy : " + this.isboy);
System.out.println("birthday : " + this.birthday);
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("lib/data.dat"));
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("lib/data.dat"));
SampleSerialize ss = new SampleSerialize(1,"Joary",true,new Date());
SampleSerialize ss1 = new SampleSerialize(2,"坤",true,new Date());
objOut.writeObject(ss);
objOut.writeObject(ss1);
SampleSerialize s = (SampleSerialize)objIn.readObject();
s.printInfo();
s = (SampleSerialize)objIn.readObject();
s.printInfo();
}
}
运行程序后,打开data文件,发现内容如下:
每个文件都是以AC ED这个数字开始的,00 05代表对象序列化格式的版本号。显然文件开头类的信息描述,系统信息及包名及类名,之后就是字段的值了。
再看下个代码:
package serialized;
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.io.Serializable;
import java.util.Date;
public class InheritSeri extends SampleSerialize{
File file = null;
Animal dog = new Animal("dog","swety");
public InheritSeri(int id, String name, boolean isboy, Date birthday) {
super(id, name, isboy, birthday);
// TODO Auto-generated constructor stub
file = new File("c:/data");
}
public void printInfo() {
super.printInfo();
this.dog.printInfo();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("lib/data1.dat"));
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("lib/data1.dat"));
objOut.writeObject(new InheritSeri(1,"joary",true,new Date()));
InheritSeri is = (InheritSeri)objIn.readObject();
is.printInfo();
}
}
class Animal implements Serializable{
private String category;
private String aniname;
public Animal(String category,String aniname) {
this.category = category;
this.aniname = aniname;
}
public void printInfo() {
System.out.println("category : " + this.category);
System.out.println("aniname : " + this.aniname);
}
}
类InheritSeri继承类SampleSerialize,间接实现了Serializable结口。一个进行序列化,则类中要实现序列化的域必须也实现的序列化,否则会抛出java.io.NotSerializableException。
4.Externalizable接口应用
package serialized;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class ExternalizableDemo implements Externalizable{
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
System.out.println("外部化输入");
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
System.out.println("外部化输出");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(new ExternalizableDemo());
ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bai);
ExternalizableDemo ed = (ExternalizableDemo)ois.readObject();
}
}
利用Externalizable接口,可以自己定制序列化类的具体的项,要存哪些项,不要存哪些项都由人来手工完成。虽然工作加大了,但更加便利。
package serialized;
import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
public class InheritSeri extends SampleSerialize{
File file = null;
Animal dog = new Animal("dog","swety");
public InheritSeri(int id, String name, boolean isboy, Date birthday) {
super(id, name, isboy, birthday);
// TODO Auto-generated constructor stub
file = new File("c:/data");
}
public void printInfo() {
super.printInfo();
this.dog.printInfo();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("lib/data1.dat"));
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("lib/data1.dat"));
objOut.writeObject(new InheritSeri(1,"joary",true,new Date()));
InheritSeri is = (InheritSeri)objIn.readObject();
is.printInfo();
}
}
class Animal implements Externalizable{
private String category;
private String aniname;
public Animal() {
}
public Animal(String category,String aniname) {
this.category = category;
this.aniname = aniname;
}
public void printInfo() {
System.out.println("category : " + this.category);
System.out.println("aniname : " + this.aniname);
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
System.out.println("外部化输入");
this.category = "外部化输入" + in.readUTF();
this.aniname = "外部化输入" + in.readUTF();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
System.out.println("外部化输出");
out.writeUTF(this.category);
out.writeUTF(this.aniname);
}
}
对3中的代码进行修改,使Animal类实现Externalizable接口,并继承两个方法writeExternal及readExternal。对于此例输出:
外部化输出
外部化输入
id : 1
name : joary
isboy : true
birthday : Mon Aug 16 16:10:47 CST 2010
category : 外部化输入dog
aniname : 外部化输入swety
可见实现Externalizable接口的类,序列化时,调用的是writeExternal及readExternal方法。