问题
Let's say I have objects of type A,B and C. I have 3 Maps which contain all instances of A,B and C respectively. Internally, both A and B have Maps of C. I want to be able to store and restore the state of the application at any time.
So, until today I had always serialized pyramid-like applications, where I would call serialize on the top Object, and the call would propagate to everything else. How do I deal with this situation? If I call serialize on the A map and then on the B map, aren't C instances going to be saved twice? Even if they do, will the deserialization leave the application state as it was just overwriting C instances when I deserialize the B map after deserializing the A map?
Thanks in advance.
回答1:
The Java serialization mechanism knows about multiple references to the same object and won't duplicate them. The object will be stored once, and all internal references will be kept.
After deserialization, your objects will be in the same state: only one instance and multiple references to that object.
回答2:
The Javadoc of ObjectOutputStream writes:
The method writeObject is used to write an object to the stream. Any object, including Strings and arrays, is written with writeObject. Multiple objects or primitives can be written to the stream. The objects must be read back from the corresponding ObjectInputstream with the same types and in the same order as they were written.
and
References to other objects (except in transient or static fields) cause those objects to be written also. Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.
In particular, if the same object is written repeatedly into an ObjectOutputStream
, its data is only written once.
You can verify this by running the following program:
class A implements Serializable {
C c;
}
class B implements Serializable {
C c;
}
class C implements Serializable {
}
public class Test {
public static void main(String[] args) throws Exception {
C c = new C();
A a = new A();
a.c = c;
B b = new B();
b.c = c;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(a);
oos.writeObject(b);
oos.writeObject(c);
}
byte[] data = baos.toByteArray();
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
A newA = (A) ois.readObject();
B newB = (B) ois.readObject();
C newC = (C) ois.readObject();
System.out.println(newA.c == newC && newB.c == newC); // prints "true"
}
}
}
回答3:
The best thing to do is to go back to your "pyramid-like" model, by storing your maps in a single object, and serializing this object;
public class ApplicationState implements Serializable {
private Map<Foo, A> aMap;
private Map<Bar, B> bMap;
}
The serialization mechanism handles graphs and multiple instances of the same object without any problem.
来源:https://stackoverflow.com/questions/10374604/serialization-of-related-objects-in-java