简体   繁体   English

readObject/writeObject 在序列化中的使用

[英]Uses of readObject/writeObject in Serialization

I was going through this article to understand more about Java Serialization process.我正在阅读这篇文章以了解更多关于 Java 序列化过程的信息。 When it comes to uses of readObject/writeObject I could see two use cases:当涉及到readObject/writeObject的使用时,我可以看到两个用例:

  1. We can use writeObject to encrypt the byte code before it gets serialized.我们可以在序列化之前使用writeObject来加密字节码。 From the security point of view, that's good thing.从安全的角度来看,这是件好事。
  2. we can use readObject to execute any specific piece of code that need to execute immediately after deserialization, and off course from poin#1, we can even use readObject to decrypt the byte code that was excrypted while serializing the object.我们可以使用readObject来执行任何需要在反序列化后立即执行的特定代码,当然从第 1 点开始,我们甚至可以使用readObject来解密在序列化 object 时被加密的字节码。

Is there any other practical scenario you've come across while serializing/deserializing objects by writing customr readObject/writeObject method?在通过编写自定义 readObject/writeObject 方法序列化/反序列化对象时,您是否遇到过任何其他实际场景? Or If you could point me to any place where I could see some decent and practical uses of readObject/writeObject?或者,如果您能指出我可以看到 readObject/writeObject 的一些体面和实际用途的任何地方?

Custom readObject methods are also useful when you need to initialize transient (non-serialized) fields after the object has been deserialized.当您需要在对象反序列化后初始化瞬态(非序列化)字段时,自定义readObject方法也很有用。


BTW, check out Effective Java, Chapter 11 (I'm not sure what the chapter/item number is in the 2nd ed.).顺便说一句,请查看Effective Java,第 11 章(我不确定第二版中的章节/项目编号是多少)。 It's an excellent read on serialization.这是一本关于序列化的优秀读物。

You can implement you own readObject/writeObject for performance reasons, or backward compatibility reasons, or because a field you want to serialize is not Serializable.出于性能原因或向后兼容性原因,或者因为要序列化的字段不是可序列化的,您可以实现自己的 readObject/writeObject。

For good examples of readObject/writeObject I would look in the source which comes with the JDK.对于 readObject/writeObject 的好例子,我会查看 JDK 附带的源代码。 Or I would try http://www.google.co.uk/search?q=readObject+writeObject+examples或者我会尝试http://www.google.co.uk/search?q=readObject+writeObject+examples

There could be several reasons for using custom serialization:使用自定义序列化可能有几个原因:

  1. Performance.表现。
  2. Interfacing with external systems.与外部系统接口。 (Beyond-your-reach or even simply non-Java systems.) (超出您的能力范围,甚至只是非 Java 系统。)
  3. Needing a human-readable format.需要一种人类可读的格式。
  4. Support for older versions of serialized classes.支持旧版本的序列化类。

To name just a few, but I'm sure there are many more.仅举几例,但我相信还有更多。

public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    private int empno;
    private String ename;
    private String job;

    // setter & getter

    @Override
    public String toString() {
        return "Employee [empno=" + empno + ", ename=" + ename + ", job=" + job
                + "]";
    }

    private void writeObject(ObjectOutputStream out) throws IOException {

        // default serialization
        // out.defaultWriteObject();

        // custom serialization
        out.writeInt(empno);
        out.writeUTF(ename);
        // out.writeUTF(job); //job will not serialize
    }

    private void readObject(ObjectInputStream in) throws IOException,
            ClassNotFoundException {

        // default deSerialization
        // in.defaultReadObject();

        // custom deSerialization
        empno = in.readInt();
        ename = in.readUTF();
        // this.job = in.readUTF();
    }

}

I thing decrypting can better be done by using an ObjectOutputStream based on an CipherOutputsStream.通过使用基于 CipherOutputsStream 的 ObjectOutputStream,可以更好地进行解密。

The most important use of writeObject/readObject is if you want to keep Serialization stable over multiple code revisions. writeObject/readObject 最重要的用途是如果您想在多次代码修订中保持序列化稳定。 Your internal representation (member variables) may change but serialization has to be stable as there are old system you communicate with (eg by reading old data from files).您的内部表示(成员变量)可能会更改,但序列化必须稳定,因为您与旧系统通信(例如,通过从文件中读取旧数据)。

But I prefer the Externalizable interface for these cases as it is easier to use (no implicit calls and methods which only the jvm knows about).但是我更喜欢这些情况下的 Externalizable 接口,因为它更容易使用(没有只有 jvm 知道的隐式调用和方法)。

The writeObject() and readObject() methods are also used for prevention of an Object Serialization. writeObject() 和 readObject() 方法也用于防止对象序列化。

When a Super class implements Serializable all of its subclasses are serializable by default.当 Super 类实现 Serializable 时,它​​的所有子类默认都是可序列化的。 But if you want a sub class not to be serializable, override the methods writeObject() and readObject() in the subclass as below但是,如果您希望子类不可序列化,请覆盖子类中的 writeObject() 和 readObject() 方法,如下所示

class Parent implements Serailizable
{
    int id;

} 

class child extends Parent
{
   String name;

   private void writeObject(ObjectOutputStream out) throws NotSerializableException
    {
        throw new NotSerializableException();
    }
    
    private void readObject(ObjectInputStream in) throws NotSerializableException
    {
        throw new NotSerializableException();
    }

}

Now the objects of subclass cannot be serialized.现在子类的对象不能被序列化。

One interesting use case for readObject is implementation of serializible Singleton, where we want the Singleton instance to persist the field values that were defined before serialization. readObject的一个有趣用例是可序列化 Singleton 的实现,我们希望 Singleton 实例保留在序列化之前定义的字段值。 So, during deserialization of the Singleton instance, we want field values to be exactly the same as before serialization, even tho they could be changed before serialization and deserialization.因此,在 Singleton 实例的反序列化期间,我们希望字段值与序列化之前完全相同,即使它们可以在序列化和反序列化之前更改。

@Serial
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
    boolean deserializedField = objectInputStream.readFields().get("field", isField());
    instance.setField(deserializedField);
}

@Serial
public Object readResolve() {
    return instance;
}

Additionaly, we need another useful method readResolve here to always return reference to a singleton instance instead of deserialized object.另外,我们在这里需要另一个有用的方法readResolve来始终返回对 singleton 实例的引用,而不是反序列化的 object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM