Java中的自定义序列化

时间:2011-09-03 13:54:30

标签: java serialization

我有以下课程

class UserAccount implements Serializable
{
    public String username;
    public String password;

    public UserAccount()
    {
        username = "defaultUsername";
        password = "defaultPassword";
    }

    public UserAccount(String u, String p)
    {
        username = u;
        password = p;
    }

    private void readObject(ObjectInputStream o) 
            throws IOException, ClassNotFoundException
    {
        //username = (String)o.readObject();
        o.defaultReadObject();
    }

    private void writeobject(ObjectOutputStream o) 
            throws IOException, ClassNotFoundException
    {
        //o.defaultWriteObject();

        o.writeObject(username);
    }

    public String toString()
    {
        return username + ", " + password;
    }
}

我编写了以下代码片段来序列化和反序列化它的实例。

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("out.dat")));

out.writeObject(new UserAccount("test", "test2"));

out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("out.dat")));

UserAccount u = (UserAccount)in.readObject();

in.close();

System.out.println(u);

我正在使用writeObject()挂钩自定义序列化,这样我只会持久化username。但是当我回读对象时,我会进行默认的反序列化。

我希望输出为test, null,而输出为test, test2

基本上我期待成员passwordnull,因为我没有坚持下去。任何人都可以帮助我了解如何将密码初始化为test2

我还验证了在反序列化过程中没有发出对构造函数的调用[我知道它不会被创建,但我仍然会检查]。

提前致谢。

2 个答案:

答案 0 :(得分:5)

使用transient关键字对变量进行序列化。这可能是斯卡弗曼答案的另一种解决方案。

参考:Why does Java have transient fields?

答案 1 :(得分:3)

writeObject()不会替换默认的序列化机制,它会添加它(允许您向流中添加其他数据)。

如果您想要一个完全自定义的机制,请考虑实施java.io.Externalizable而不是java.io.Serializable

来自javadoc

  

只有Externalizable实例的类的标识写在序列化流中,类的责任是保存和恢复其实例的内容。 writeExternal接口的readExternalExternalizable方法由类实现,以使类完全控制对象及其超类型的流的格式和内容。这些方法必须明确地与超类型协调以保存其状态。这些方法取代了writeObjectreadObject方法的自定义实现。