更改实例状态不会反映在序列化对象中 [英] Changing instance state does not get reflected in serialized object

查看:194
本文介绍了更改实例状态不会反映在序列化对象中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了以下简单代码

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]

我无法理解为什么它不打印

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?

推荐答案

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

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.

但所有这些都说: ObjectOutputStream 只写一个给定的对象,然后对同一个对象的后续写入将引用写入它,而不是它的第二个副本。来自文档

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.

这个想法是你将一次序列化对象图。在序列化期间对对象图进行变换是一件非常奇怪的事情。我找不到任何文档说它不受支持,但是在项目中添加第二个读取仍然显示Test而不是Test123,所以......

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...

要写出两个单独的 Human 对象,您需要在写入之前创建第二个:

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));
    }
}

...输出:


Human : [Human 21, Test]
newHuman1 :[Human 21, Test]
newHuman2 :[Human 21, Test]
Same object? true

这篇关于更改实例状态不会反映在序列化对象中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆