Java中的序列化
一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。
一、先让我们实现一个具有序列化能力的类:
import java.io.*;
/**
* 实现具有序列化能力的类
* */
public class SerializableDemo implements Serializable{
public SerializableDemo(){
}
public SerializableDemo(String name, int age){
this.name=name;
this.age=age;
}
@Override
public String toString(){
return "姓名:"+name+" 年龄:"+age;
}
private String name;
private int age;
}
二、使用ObjectOutputStream输出序列化后的内容:
public class ObjectOutputStreamDemo{
public static void main(String[] args) throws IOException{
File file = new File("d:" + File.separator + "hello.txt");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
file));
oos.writeObject(new Person("rollen", 20));
oos.close();
}
}
【运行结果】:
当我们查看产生的hello.txt的时候,看到的是乱码,呵呵。因为是二进制文件。
三、使用ObjectInputStream反序列化该类型:
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
/**
* ObjectInputStream示范
* */
public class ObjectInputStreamDemo{
public static void main(String[] args) throws Exception{
File file = new File("d:" + File.separator + "hello.txt");
ObjectInputStream input = new ObjectInputStream(new FileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}
【运行结果】
姓名:rollen 年龄:20
四、使用Externalizable接口来自定义序列化
被Serializable接口声明的类的对象的属性都将被序列化,但是如果想自定义序列化的内容的时候,就需要实现Externalizable接口。使用Externalizable接口可以控制序列化哪些属性,而不序列化哪些属性。
当一个类要使用Externalizable这个接口的时候,这个类中必须要有一个无参的构造函数,如果没有的话,在构造的时候会产生异常,这是因为在反序列话的时候会默认调用无参的构造函数。
现在我们来演示一下序列化和反序列话:
import java.io.*;
import java.util.*;
//本程序通???Externalizable接口控制?象序列化和反序列
public class UserInfo implements Externalizable {
public String userName;
public String userPass;
public int userAge;
public UserInfo(){
}
public UserInfo(String username,String userpass,int userage){
this.userName=username;
this.userPass=userpass;
this.userAge=userage;
}
//当序列化?象?,?方法自??用
public void writeExternal(ObjectOutput out) throws IOException{
System.out.println("?在?行序列化方法");
//可以在序列化?写非自身的?量
Date d=new Date();
out.writeObject(d);
//只序列化userName,userPass?量
out.writeObject(userName);
out.writeObject(userPass);
}
//当反序列化?象?,?方法自??用
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{
System.out.println("?在?行反序列化方法");
Date d=(Date)in.readObject();
System.out.println(d);
this.userName=(String)in.readObject();
this.userPass=(String)in.readObject();
}
public String toString(){
return "用?名: "+this.userName+";密?:"+this.userPass+
";年?:"+this.userAge;
}
}
测试类
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.lang.management.*;
public class Test {
//序列化?象到文件
public static void serialize(String fileName){
try
{
//?建一个?象?出流,??象?出到文件
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));
UserInfo user=new UserInfo("renyanwei","888888",20);
out.writeObject(user); //序列化一个会??象
out.close();
}
catch (Exception x)
{
System.out.println(x.toString());
}
}
//从文件反序列化到?象
public static void deserialize(String fileName){
try
{
//?建一个?象?入流,从文件?取?象
ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));
//?取UserInfo?象并?用它的toString()方法
UserInfo user=(UserInfo)(in.readObject());
System.out.println(user.toString());
in.close();
}
catch (Exception x)
{
System.out.println(x.toString());
}
}
public static void main(String[] args) {
serialize("D:\\test.txt");
System.out.println("序列化完?");
deserialize("D:\\test.txt");
System.out.println("反序列化完?");
}
}
【运行结果】:
现在执行序列化方法
序列化完毕
现在执行反序列化方法
Thu Oct 23 22:18:12 CST 2008
用户名: renyanwei;密码:888888;年龄:0
反序列化完毕
五、使用transient来控制序列化的内容
Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,
当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:
package IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 序列化和反序列化的操作
* */
public class serDemo{
public static void main(String[] args) throws Exception{
ser(); // 序列化
dser(); // 反序列话
}
public static void ser() throws Exception{
File file = new File("d:" + File.separator + "hello.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
file));
out.writeObject(new Person1("rollen", 20));
out.close();
}
public static void dser() throws Exception{
File file = new File("d:" + File.separator + "hello.txt");
ObjectInputStream input = new ObjectInputStream(new FileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}
class Person1 implements Serializable{
public Person1(){
}
public Person1(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString(){
return "姓名:" + name + " 年龄:" + age;
}
// 注意这里
private transient String name;
private int age;
}
【运行结果】:
姓名:null 年龄:20
六、数组的序列化
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 序列化一组对象
* */
public class SerDemo1{
public static void main(String[] args) throws Exception{
Student[] stu = { new Student("hello", 20), new Student("world", 30),
new Student("rollen", 40) };
ser(stu);
Object[] obj = dser();
for(int i = 0; i < obj.length; ++i){
Student s = (Student) obj[i];
System.out.println(s);
}
}
// 序列化
public static void ser(Object[] obj) throws Exception{
File file = new File("d:" + File.separator + "hello.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
file));
out.writeObject(obj);
out.close();
}
// 反序列化
public static Object[] dser() throws Exception{
File file = new File("d:" + File.separator + "hello.txt");
ObjectInputStream input = new ObjectInputStream(new FileInputStream(
file));
Object[] obj = (Object[]) input.readObject();
input.close();
return obj;
}
}
class Student implements Serializable{
public Student(){
}
public Student(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString(){
return "姓名: " + name + " 年龄:" + age;
}
private String name;
private int age;
}
【运行结果】:
姓名: hello 年龄:20
姓名: world 年龄:30
姓名: rollen 年龄:40
七、把类型序列化为XML格式
序列化、反序列化为XML文件,我使用了XStream来序列化,需要引入xstream-1.3.1.jar包的支持,
http://xstream.codehaus.org/download.html 处可以下载jar,然后引入到Eclipse中的build path中。
public class Person implements Serializable{
private String name;
private int age;
public Person(){
}
public Person(String str, int n){
System.out.println("Inside Person's Constructor");
name = str;
age = n;
}
String getName(){
return name;
}
int getAge(){
return age;
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import com.thoughtworks.xstream.*;
public class Serialize {
public static void main(String[] args) {
Serialize ser = new Serialize();
ser.serializeToXml();
ser.deSerializeFromXml();
}
public void serializeToXml(){
Person[] myPerson = new Person[2];
myPerson[0] = new Person("Jay",24);
myPerson[1] = new Person("Tom",23);
XStream xstream = new XStream();
try {
FileOutputStream fos = new FileOutputStream("E:\\workspace\\2010_03\\src\\myPerson.xml");
xstream.toXML(myPerson,fos);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
System.out.println(xstream.toXML(myPerson));
}
public void deSerializeFromXml(){
XStream xs = new XStream();
Person[] myPerson = null;
try {
FileInputStream fis = new FileInputStream("E:\\workspace\\2010_03\\src\\myPerson.xml");
myPerson=(Person[])xs.fromXML(fis);
if (myPerson != null)
{
int len = myPerson.length;
for (int i=0;i<len;i++)
{
System.out.println(myPerson[i].getName());
System.out.println(myPerson[i].getAge());
}
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
}
【运行结果】:
Inside Person's Constructor
Inside Person's Constructor
Jay
24
Tom
23
输出的XML文件为:
<Person-array>
<Person>
<name>Jay</name>
<age>24</age>
</Person>
<Person>
<name>Tom</name>
<age>23</age>
</Person>
</Person-array>