当前位置: 首页 > 面试题库 >

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

郗阳德
2023-03-14
问题内容

我写了下面的简单代码

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只写一次给定的对象,然后对该对象的后续写操作只 引用
该对象,而不是该对象的第二个副本。从文档中:

对象的默认序列化机制将写入对象的类,类签名以及所有非瞬态和非静态字段的值。对其他对象的引用(在瞬态或静态字段中除外)会使这些对象也被写入。使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图恢复为与原始文档相同的形状。

这个想法是,您将一次序列化所有对象图。 序列化 过程中
更改对象图是一件很奇怪的事情。我找不到任何文档说它不被支持,但是向您的项目添加第二读仍然显示“ 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));
    }
}

…输出:

人类:[人类21,测试]
newHuman1:[Human 21,测试]
newHuman2:[Human 21,测试]
同一个对象?真正


 类似资料:
  • 在这种情况下,我更改选择元素并调用数据更新方法。该方法从状态获取值。但是当数据更新时,状态还没有改变。当您再次调用数据更新时,状态已经更新了如何正确进行更新? 反应成分

  • 我使用带有WebFlux的Spring boot 2.0.1作为Rest服务器。 在我RestController我想自动反序列化一个对象(产品)。但是我得到一个杰克逊错误,好像参数名称模块没有注册。 原因:com.fasterxml.jackson.databind.exc.Invalid定义异常:无法构建的实例(没有像默认构造一样的Creator):无法从对象值(没有基于委托或属性的Creat

  • 我正在使用ReactJS、Typescript和Firebase构建一个web应用程序,其中一个用户将能够监视与另一个用户的UI的更改和交互。两个用户可以同时看到相同的视图,并显示一些图像。例如,User1单击的任何图像都会更改其边框,这应该反映在User2的UI中。单独使用DOM、typescript和firebase是可行的,但是使用ReactJS我面临很多困难。 第一个问题:是否可以在不使用

  • 有一个类实现,但在第一个版本中没有定义。在下一个版本中,我提供了。 现在的问题是,每当我试图反序列化之前存储的对象时,都会出现错误: 静态最终长serialVersionUID=4061053075992556495L;但需要com.example.android.user:静态final long serialVersionUID=-1079331593441085712L;

  • 我正在Laravel5.1中创建一个应用程序,它以前工作得很好。我在视图文件中所做的任何更改都会反映在浏览器中。现在,在过去3天中,浏览器中未反映任何更改。 以下是我的视图文件: 主人刀身php 我正在将css文件的名称更改为app。但是当我运行应用程序时,它会显示main。源代码中的css。 我在storage/framework中查找了缓存,它显示了带有旧代码“main”的视图文件。css“我

  • 编辑:这是在添加到购物车按钮onclick事件时执行的函数: addToCart action creator如下所示: