java序列化和反序列化

来源:互联网 发布:ipad1安装不了软件 编辑:程序博客网 时间:2024/06/18 03:50

JAVA序列化和反序列化的方式主要有两种:


1.实现Serializable接口:

相应的对象实现了序列化接口Serializable,这个使用的比较多,对于序列化接口Serializable接口是一个空的接口,它的主要作用就是标识这个对象时可序列化的,jre对象在传输对象的时候会进行相关的封装


2.实现Externalizable接口:

Externalizable接口继承了Serializable接口,并增加了两个方法

void writeExternal(ObjectOutput out) throws IOException;

        void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;

      首先,我们在序列化对象的时候,由于这个类实现了Externalizable 接口,在writeExternal()方法里定义了哪些属性可以序列化,哪些不可以序列化,所以,对象在经过这里就把规定能被序列化的序列化保存文件,不能序列化的不处理,然后在反序列的时候自动调

用readExternal()方法,根据序列顺序挨个读取进行反序列,并自动封装成对象返回,然后在测试类接收,就完成了反序列。

       所以说Exterinable的是Serializable的一个扩展。


package com.xiaohao.test;
 
import java.io.Externalizable;
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.text.SimpleDateFormat;
import java.util.Date;
 
 
/**
 * 测试实体类
 * @author 小浩
 * @创建日期 2015-3-12
 */
class Person implements Externalizable{
        private static final long serialVersionUID = 1L;<br>    String userName;
    String password;
    String age;
     
   
    public Person(String userName, String password, String age) {
        super();
        this.userName = userName;
        this.password = password;
        this.age = age;
    }
     
     
    public Person() {
        super();
    }
 
 
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
     
    /**
     * 序列化操作的扩展类
     */
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        //增加一个新的对象
        Date date=new Date();
        out.writeObject(userName);
        out.writeObject(password);
        out.writeObject(date);
    }
     
    /**
     * 反序列化的扩展类
     */
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        //注意这里的接受顺序是有限制的哦,否则的话会出错的
        // 例如上面先write的是A对象的话,那么下面先接受的也一定是A对象...
        userName=(String) in.readObject();
        password=(String) in.readObject();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date date=(Date)in.readObject();       
        System.out.println("反序列化后的日期为:"+sdf.format(date));
         
    }
    @Override
    public String toString() {
        //注意这里的年龄是不会被序列化的,所以在反序列化的时候是读取不到数据的
        return "用户名:"+userName+"密 码:"+password+"年龄:"+age;
    }
}
 
 
/**
 * 序列化和反序列化的相关操作类
 * @author 小浩
 * @创建日期 2015-3-12
 */
class Operate{
    /**
     * 序列化方法
     * @throws IOException
     * @throws FileNotFoundException
     */
    public void serializable(Person person) throws FileNotFoundException, IOException{
        ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("a.txt"));
        outputStream.writeObject(person);      
    }
     
    /**
     * 反序列化的方法
     * @throws IOException
     * @throws FileNotFoundException
     * @throws ClassNotFoundException
     */
    public Person deSerializable() throws FileNotFoundException, IOException, ClassNotFoundException{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt"));
        return (Person) ois.readObject();
    }
     
 
     
}
/**
 * 测试实体主类
 * @author 小浩
 * @创建日期 2015-3-12
 */
public class Test{
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
       Operate operate=new Operate();
       Person person=new Person("小浩","123456","20");
       System.out.println("为序列化之前的相关数据如下:\n"+person.toString());
       operate.serializable(person);
       Person newPerson=operate.deSerializable();
       System.out.println("-------------------------------------------------------");
       System.out.println("序列化之后的相关数据如下:\n"+newPerson.toString());
    }
     
     
}

注意问题:

1.对于不想序列化的字段可以使用transient声明。使用transient声明的字段不参与序列化。

2.serialVersionUID必不可少。没有serialVersionUID时,序列化时会根据字段和特性的算法生成一个serialVersionUID,但是当对象的属性(增加或者减少字段)发生变化时,serialVersionUID会发生变化,则反序列化失败.