CSC/ECE 517 Fall 2009/wiki2 18 i7: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 51: Line 51:


== Idiomatic Usage ==
== Idiomatic Usage ==
The usual way this is implemented is using an inner class that is declared as static and final.  The reason the class is declared static is because it should not share any instance variables with the parent and final because this class should never be extended.  Additionally since the class is hidden because it is an inner class, the serialization proxy used will be transparent to all users of this class regarding serialization.  This is a good thing because we don't want users of this class to have to deal with the serialization proxy.  An example of this structure is the following.
The idiom for implementing serialization proxy pattern is using an inner class that is declared as static and final.  The reason the class is declared static is because it should not share any instance variables with the parent and final because this class should never be extended.  Additionally since the class is hidden because it is an inner class, the serialization proxy used will be transparent to all users of this class regarding serialization.  This is a good thing because we don't want users of this class to have to deal with the serialization proxy.  An example of this structure is the following.


<pre>
<pre>

Revision as of 04:52, 9 October 2009

Serialization Proxy Pattern

Problem

When designing a class, it is preferred to have them be immutable because of guaranteed thread safety and consistent object state. An immutable class is one where the state cannot be modified after it is instantiated.

A problem arises in Java when needing a class to be serializable. In order to have a class be serializable the Serializable interface must be implemented. A class that is serializable is one that can be represented on disk as a sequence of bits. The reason this is a problem is not on serialization, but rather on deserialization. During deserialization of a class, Java requires that the first non-serializable superclass have a no-argument constructor. Java uses this constructor to instantiate the object and populate the fields. This may be the case if the superclass is one that is immutable. The answer here in most cases would be to make the class and superclass mutable and provide a no argument constructor in the superclass. Serialization proxy pattern aims to solve this problem.

Design

The idea behind the serialization proxy pattern is simple. On serialization, instead of having to remove the immutability that exists in the superclass and the class that needs to be serialized, a proxy class is serialized instead of the target class. A proxy class in this context would be a class where enough information is stored in it to reconstruct the target class. On deserialization, instead of returning an instance of the proxy class, the target class is instantiated with the information provided by the proxy class and returned in place of it. The following diagram shows the design of what happens on serialization and deserialization.

Implementation Details

During serialization there is a method that Java looks for which is called writeReplace. If writeReplace exists, the value returned from this method will be serialized in place of the current class. This is where we would return a proxy object which stores enough information to reconstruct what we actually want to serialize. An example of an implementation of writeReplace can be identified in the following code snippet. In brief, there is a simple class called MyClass which holds a single integer value and there is an inner class SerializationProxy. The SerializationProxy class used as the serialization proxy object in the writeReplace method when serializing instances of MyClass.

public class MyClass implements Serializable {
    private final int value;
    
    public MyClass(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    private Object writeReplace() {
        return new SerializationProxy(this);
    }

    private static final class SerializationProxy implements Serializable {
        private final int value;

        public SerializationProxy(MyClass myClass) {
            this.value = myClass.getValue();
        }
    }
}


During deserialization there is a method that Java looks for which is called readResolve. If readResolve exists, the value returned from this method will instead be the result of the deserialization of this object. This method would be implemented in the proxy class and the constructor for the class we want to reconstruct would be invoked and returned as the value returned by readResolve. An example implementation of readResolve would be the following which would be added inside of the SerializationProxy class from the previous example.

private Object readResolve() {
    return new MyClass(this.value);
}

Idiomatic Usage

The idiom for implementing serialization proxy pattern is using an inner class that is declared as static and final. The reason the class is declared static is because it should not share any instance variables with the parent and final because this class should never be extended. Additionally since the class is hidden because it is an inner class, the serialization proxy used will be transparent to all users of this class regarding serialization. This is a good thing because we don't want users of this class to have to deal with the serialization proxy. An example of this structure is the following.

public class MyClass implements Serializable {
    ...
    private static final SerializationProxy implements Serializable {
        ...
    }
}

References

1. Java API - Serializable

2. jGuru - Are classes that implement Serializable required to have no-argument constructors?

3. Effective Java

4. Wikipedia - Immutable object

5. Wikipedia - Serialization