Java序列化之Externalizable

前篇介绍了标识了transient与static的变量是不被序列化的,以下介绍更为灵活控制对象序列化和反序列化的方法,甚至可以控制序列化非本类的数据。
一、接口介绍
当对象继承了java.io.Externalizable接口时,可以更灵活得控制整个序列化与反序列化的过程。以下是java.io.Externalizable接口的关系图:
从上图中可以看出,java.io.Externalizable接口继承了java.io.Serializable接口,以此可知实现了java.io.Externalizable接口后,类可以被序列化和反序列化。
java.io.Externalizable源代码
public interface Externalizable extends java.io.Serializable {
/**
* The object implements the writeExternal method to save its contents
* by calling the methods of DataOutput for its primitive values or
* calling the writeObject method of ObjectOutput for objects, strings,
* and arrays.
*
* @serialData Overriding methods should use this tag to describe
* the data layout of this Externalizable object.
* List the sequence of element types and, if possible,
* relate the element to a public/protected field and/or
* method of this Externalizable class.
*
* @param out the stream to write the object to
* @exception IOException Includes any I/O exceptions that may occur
*/
void writeExternal(ObjectOutput out) throws IOException; /**
* The object implements the readExternal method to restore its
* contents by calling the methods of DataInput for primitive
* types and readObject for objects, strings and arrays. The
* readExternal method must read the values in the same sequence
* and with the same types as were written by writeExternal.
*
* @param in the stream to read data from in order to restore the object
* @exception IOException if I/O errors occur
* @exception ClassNotFoundException If the class for an object being
* restored cannot be found.
*/
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}

以上代码可以看出,java.io.Externalizable接口声明了两个方法writeExternal(ObjectOutput out)和readExternal(ObjectInput in)。
writeExternal(ObjectOutput out):当对象进行序列化时,此方法会被执行,该对象需要序列化哪些数据可在此方法进行实现。
readExternal(ObjectInput in):当对象进行反序列化时,此方法会被执行,需要反序列哪些字段在此方法中实现。
二、实践
实现java.io.Externalizable的类
public class User implements Externalizable{
    private static final long serialVersionUID = 1L; private String loginName;
    private String password;
    private String name;
    private String sex;
    public User() {
    }
    public User(String loginName, String password, String name, String sex) {
        this.loginName = loginName;
        this.password = password;
        this.name = name;
        this.sex = sex;
    }
    public String getLoginName() {
        return loginName;
    }
    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "User{" +
            "loginName='" + loginName + '\'' +
            ", password='" + password + '\'' +
            ", name='" + name + '\'' +
            ", sex='" + sex + '\'' +
            '}';
    }
    public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("开始序列化-------------------------");
        out.writeObject(loginName);
        out.writeObject(name);
        out.writeObject(sex);
        out.writeObject(new Date());//不存在当前类也可以被序列化
    }
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("开始反序列化------------------------");
        this.loginName = (String) in.readObject();
        this.name = (String)in.readObject();
        this.sex = (String)in.readObject();
        System.out.println(((Date)in.readObject()).toString());
    }
}

序列化代码片段
public void externalizable(){
    try {
        User user = new User("login.test", "123456", "test", "男");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("User.txt"));
        oos.writeObject(user);
        oos.flush();
        oos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

控制台结果
开始序列化-------------------------
序列化后文件:
User.txt

反序列化代码片段
public void dexternalizable(){
    try {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("User.txt"));
        User user = (User)ois.readObject();
        System.out.println(user);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

控制台结果
开始反序列化------------------------
Tue Oct 25 23:07:34 CST 2016
User{loginName='login.test', password='null', name='test', sex='男'}
以上结果可以看出:
1、序列化时,执行了writeExternal(ObjectOutput out)方法;
2、反序列化时,执行了readExternal(ObjectInput in)方法;
3、writeExternal(ObjectOutput out)方法中序列化了当前日期,在反序列化时成功获得了日期数据。
4、password字段并没有被序列化。
注意点:
1、在序列化方法中,写入了几个字段且写入的顺序,在反序列化方法中必须按照序列化方法中的顺序及数量获取,否则有可能出现反序列化数据类型不对或sex字段的值给赋值到name字段上。
2、如以上例子,若反序列化方法中没有反序列sex字段,那么就无法取得Date数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值