问题
I wrote following simple code
public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("data.txt")));
Human human = new Human();
human.setAge(21);
human.setName("Test");
System.out.println("Human : " + human);
oos.writeObject(human);
human.setName("Test123");
oos.writeObject(human);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("data.txt")));
Human newHuman1 = (Human)ois.readObject();
System.out.println("newHuman1 :" + newHuman1);
Human newHuman2 = (Human)ois.readObject();
System.out.println("newHuman2 :" + newHuman2);
}
and it prints -
Human : Human [age=21, name=Test]
newHuman1 :Human [age=21, name=Test]
newHuman2 :Human [age=21, name=Test]
I am not able to understand why it does not print
newHuman2 :Human [age=21, name=Test123]
Why changing instance state does not get reflected in serialized object?
回答1:
You've written the object twice, but only read back the first one. So if two copies of the object were written, you'd need to add a second read to see the second copy. It would also probably be a good idea to close the output before you read from the file, to ensure buffers are flushed.
But all that said: ObjectOutputStream
only writes a given object once, and then subsequent writes of that same object write references to it, not a second copy of it. From the documentation:
The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. 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.
The idea is that you'll serialize object graphs all at once. Mutating the object graph during serialization is a pretty odd thing to do. I can't find any documentation saying it isn't supported, but adding a second read to your project still shows "Test" rather than "Test123", so...
To write out two separate Human
objects, you'll need to create a second one before writing:
import java.io.*;
public class Human implements Serializable {
private int age;
private String name;
public void setAge(int a) {
this.age = a;
}
public void setName(String n) {
this.name = n;
}
public String toString() {
return "[Human " + this.age + ", " + this.name + "]";
}
public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException
{
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("data.txt"))))
{
Human human = new Human();
human.setAge(21);
human.setName("Test");
System.out.println("Human : " + human);
oos.writeObject(human);
human = new Human(); // <== Change
human.setAge(21); // <== Change
human.setName("Test123");
oos.writeObject(human);
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("data.txt"))))
{
Human newHuman = (Human)ois.readObject();
System.out.println("newHuman1 :" + newHuman);
newHuman = (Human)ois.readObject();
System.out.println("newHuman2 :" + newHuman);
}
}
}
Without those lines flagged above, the second write just results in a reference to the first object. We can prove that like this:
public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException
{
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("data.txt"))))
{
Human human = new Human();
human.setAge(21);
human.setName("Test");
System.out.println("Human : " + human);
oos.writeObject(human);
human.setName("Test123");
oos.writeObject(human);
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("data.txt"))))
{
Human newHuman1 = (Human)ois.readObject();
System.out.println("newHuman1 :" + newHuman1);
Human newHuman2 = (Human)ois.readObject();
System.out.println("newHuman2 :" + newHuman2);
System.out.println("Same object? " + (newHuman1 == newHuman2));
}
}
...which outputs:
Human : [Human 21, Test] newHuman1 :[Human 21, Test] newHuman2 :[Human 21, Test] Same object? true
来源:https://stackoverflow.com/questions/27542699/changing-instance-state-does-not-get-reflected-in-serialized-object