Re: implement writeObject how? serializable singleton how?
Tom Hawtin <usenet@tackline.plus.com> writes:
Frank Fredstone wrote:
Tom Hawtin <usenet@tackline.plus.com> writes:
Frank Fredstone wrote:
If I add code to the constructor, it executes during
deserialization, so that doesn't work for me.
It shouldn't do. readObject (or a call to
ObjectInputStream.defaultReadObject) takes the place of the
constructor. For this sort of class, it doesn't really matter what the
fields are set to as you are going to dump the deserialised object.
The constructor is called during deserialization, maybe because of the
assignment to the field singleton. If I put a print statement in the
constructor, it executes during deserialization. If I use the
supposedly redundant "transient static" the constructor is still
called during deserialization. If I use transient only the constructor
is called during deserialization. If I use static final, the
constructor is called during deserialization.
Perhaps you are seeing the construction during static (class)
initialisation. When an object is deserialised the constructor of the
most derived non-serialisable class (possibly Object) is invoked by
the serialisation mechanism.
So, you and Chris Uppal's post as well, are agreeing that the
constructor is called during deserialization.
For my purposes, the singleton means "cause a side-effect only
once". I'm trying to find a way to have that behavior survive
deserialization.
Are you trying to store the state of the object? That doesn't really
make any sense. You are making and reading a copy of the singleton
state, so there is more than one of the singletons in existence.
I want an object that has a state that is initialized only once, as a
result of an external side-effect. I also want it to be possible for
that state to be serialized, without the state being "reinitialized"
(in the sense of being intitialized again by a specific block of code)
during deserialization. I want the state (the field values) restored,
without the code that initializes them during construction being
called.
In any case, I found information about writeObject in:
http://java.sun.com/j2se/1.3/docs/guide/serialization/spec/examples.doc1.html
Based on that, I have this mutation of the java developer almanac
serializable singleton that seems to survive deserialization. The
external side-effect is represented by retrieving a system property.
The one instance of the class would be normally be referenced using:
MySingleton.instance();
If it were deserialized, the reference would be faked using:
(MySingleton) objectInputStream.readObject();
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
public class MySingleton implements Serializable {
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("instance", MySingleton.class),
new ObjectStreamField("value", String.class)
};
private static MySingleton instance = null;
private String value = null;
private MySingleton() {
System.out.println("Constructing MySingleton");
}
private MySingleton(boolean f) {
System.out.println("Constructing MySingleton f");
System.out.println("Setting value to " +
System.getProperty("abc"));
value = System.getProperty("abc");
}
public String value() { return value; }
public static MySingleton instance() {
if (instance == null) {
instance = new MySingleton(true);
}
return instance;
}
private void writeObject(ObjectOutputStream s) throws IOException {
ObjectOutputStream.PutField fields = s.putFields();
fields.put("instance", instance);
fields.put("value", value);
s.writeFields();
}
private void readObject(ObjectInputStream s) throws IOException {
try {
ObjectInputStream.GetField fields = s.readFields();
instance = (MySingleton) fields.get("instance", null);
value = (String) fields.get("value", null);
} catch (ClassNotFoundException cnfe) {
throw new IOException("" + cnfe);
}
}
}