9

I was going through this article to understand more about Java Serialization process. When it comes to uses of readObject/writeObject I could see two use cases:

  1. We can use writeObject to encrypt the byte code before it gets serialized. 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.

Is there any other practical scenario you've come across while serializing/deserializing objects by writing customr readObject/writeObject method? Or If you could point me to any place where I could see some decent and practical uses of readObject/writeObject?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Vicky
  • 5,380
  • 18
  • 60
  • 83

7 Answers7

16

Custom readObject methods are also useful when you need to initialize transient (non-serialized) fields after the object has been deserialized.


BTW, check out Effective Java, Chapter 11 (I'm not sure what the chapter/item number is in the 2nd ed.). It's an excellent read on serialization.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Actually it does... I was looking for some comments on how exactly it has been used in your application. Though custom Serialization is a fancy thing, but initializing transient or static variables in readObject() is often used feature. – Vicky May 06 '11 at 15:55
  • @Vicky: "actually it does" as in, the Effective Java link answers your question? – Matt Ball May 06 '11 at 16:03
  • yes i'm now looking in the book. But your answer about initializing transient field helped me. – Vicky May 06 '11 at 16:36
5

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.

For good examples of readObject/writeObject I would look in the source which comes with the JDK. Or I would try http://www.google.co.uk/search?q=readObject+writeObject+examples

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
4
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();
    }

}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
4

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.)
  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.

biziclop
  • 48,926
  • 12
  • 77
  • 104
3

I thing decrypting can better be done by using an ObjectOutputStream based on an CipherOutputsStream.

The most important use of writeObject/readObject is if you want to keep Serialization stable over multiple code revisions. Your internal representation (member variables) may change but serialization has to be stable as there are old system you communicate with (e.g. 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).

rurouni
  • 2,315
  • 1
  • 19
  • 27
  • Is this the reason why that (for example) [Java's LinkedList implementation](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/LinkedList.java#LinkedList.writeObject%28java.io.ObjectOutputStream%29) implements the writeObject/readObject methods? – Chris Leung Dec 12 '17 at 08:03
1

The writeObject() and readObject() methods are also used for prevention of an Object Serialization.

When a Super class implements Serializable all of its subclasses are serializable by default. But if you want a sub class not to be serializable, override the methods writeObject() and readObject() in the subclass as below

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.

Nikhil Batchu
  • 23
  • 1
  • 4
0

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. 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.

@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.

jahey
  • 1