java – 更改实例状态不会反映在序列化对象中

我写了以下简单的代码

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]

为什么更改实例状态不会反映在序列化对象中?

解决方法:

你已经把对象写了两次,但只读回了第一个.因此,如果写入了两个对象副本,则需要添加第二个读取以查看第二个副本.在从文件读取之前关闭输出可能是个好主意,以确保刷新缓冲区.

但所有这一切:ObjectOutputStream只写一个给定的对象,然后对同一个对象的后续写入写入对它的引用,而不是它的第二个副本.从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.

我们的想法是,您将同时序列化对象图.在序列化期间改变对象图是一件非常奇怪的事情.我找不到任何文档说它不受支持,但是在项目中添加第二个读取仍然显示“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
上一篇:英语-20210224


下一篇:翻译:《实用的Python编程》07_05_Decorated_methods