我写了以下简单代码
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);
}
并打印 -
Human : Human [age=21, name=Test]
newHuman1 :Human [age=21, name=Test]
newHuman2 :Human [age=21, name=Test]
我无法理解为什么不打印
newHuman2 :Human [age=21, name=Test123]
为什么更改实例状态不会反映在序列化对象中?
答案 0 :(得分:5)
你已经将对象写了两次,但只回读第一个。因此,如果写入了两个对象副本,则需要添加第二个读取以查看第二个副本。在从文件读取之前关闭输出可能是个好主意,以确保刷新缓冲区。
但是所有这一切:ObjectOutputStream
只写一个给定的对象,然后对同一个对象的后续写入将引用写入它,而不是它的第二个副本。来自the documentation:
对象的默认序列化机制会写入对象的类,类签名以及所有非瞬态和非静态字段的值。对其他对象的引用(瞬态或静态字段除外)也会导致写入这些对象。使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象图形恢复为与写入原始图像时相同的形状。
这个想法是你将一次序列化对象图。在序列化期间改变对象图是一件非常奇怪的事情。我找不到任何文档说它不受支持,但是在项目中添加第二个读取仍然显示“Test”而不是“Test123”,所以......
要写出两个单独的Human
个对象,您需要在编写之前创建第二个对象:
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);
}
}
}
如果上面没有标记这些行,则第二次写入只会导致对第一个对象的引用。我们可以证明这样:
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));
}
}
......输出:
Human : [Human 21, Test] newHuman1 :[Human 21, Test] newHuman2 :[Human 21, Test] Same object? true