【问题标题】:Numbers of object created during serialization using writeUnshared()使用 writeUnshared() 在序列化期间创建的对象数
【发布时间】:2013-08-03 09:09:50
【问题描述】:

为了准备 OCPJP7 考试,我最近玩了一些序列化。 因此,我尝试序列化以下类:

class TempClass  implements Serializable {  
        int secCounter;   
        static int counter;  
        {  
                counter++;  
        }  
        {  
        secCounter=counter;  

然后当我尝试使用以下内容将对象写入FileOutputStream 时:

TempClass temp = new TempClass();  
ObjectOutputStream obi = new ObjectOutputStream(new FileOutputStream(file));   
obi.writeObject(temp);  
obi.writeUnshared(temp);  
obi.writeUnshared(temp);  

因此,当我使用ObjectInputStream 回读它们时,我得到了 3 个不同的对象,因此创建了 3 个对象。 然而,secCounter 的最终值是一个实例变量,因此可以被序列化,它是 1 而不是 3。 1 是我调用new 关键字的次数,所以我认为当使用obi.writeUnshared(object) 创建对象时,构造函数会以不同的方式处理。 有人知道到底发生了什么吗?我知道静态变量没有序列化,但是在上面发布的代码中,我将值从静态变量复制到实例变量secCounter。 因此,最终再次检查成功序列化的 secCounter 的值不会让我得到预期的(至少对我而言)结果,而是 1。

提前致谢。

【问题讨论】:

    标签: java serialization io


    【解决方案1】:

    序列化过程中创建的对象数量 ...

    Zero 对象是在序列化过程中创建的,就本问题而言。

    因此创建了 3 个对象。

    writeUnshared() 不会创建任何对象。 反序列化时创建对象。

    但是 secCounter 的最终值是 1 而不是 3,它是一个可以序列化的实例变量。

    证明了这一点。序列化时不创建对象。

    1 是我调用 new 关键字的次数,所以我认为当使用obi.writeUnshared() 创建对象时,构造函数会以不同的方式处理

    再一次,此方法不会创建任何对象。没有调用构造函数。 不会在 writeUnshared() 中发生的是将“句柄”序列化为现有序列化对象。 现在的对象已被序列化,而不是一个句柄,该句柄将被反序列化为对先前反序列化实例的引用。

    【讨论】:

    • 问题是当他读回它们时,而不是在序列化时。
    • @EJP 但是当我读回它们时,它们有不同的 toString() 因此是不同的对象.. 然而即使最后一次读取,secCounter 的值仍然是 1。
    • @Rolerball 没错。您对“复制”或“克隆”或“构建”何时发生感到困惑。它不会发生在发送方,也不会通过构造发生,因此您期望执行的代码不会执行。
    • @EJP 但是最终结果是我有 3 个不同的对象。我知道第一个是如何创建的,我是用“new”创建的。另外两个呢?它们是什么时候创建的?我说的是用 write.Unshared() 序列化的那些,然后读回并放入参考。
    • 我已经回答过了。在反序列化过程中。
    【解决方案2】:

    在不执行反序列化构造函数(或初始化程序,如您的情况)期间,这是因为当您反序列化对象时,您很可能期望对象的内部状态与原始对象的状态相同。运行初始化程序或构造函数可能会产生“副作用”,例如修改对象的内部状态。

    【讨论】:

    • 那么拥有一个新的(但相同的)对象有什么好处呢?只使用不会创建克隆的 writeObject(ob) 不是更好吗?
    • @Rollerball writeUnshared() 也不会“创建克隆”。您对流程的理解存在严重缺陷。
    • @EJP 好的,我应该有“”这个词克隆......并不意味着克隆与使用 clone() 方法相同,对此我很抱歉。但是,我的意思是另一个具有与“共享”相同状态的对象,因此由 writeObject 而不是 writeUnshared 编写
    • 如果您使用 ObjectInputStream.readObject() 反序列化,您将拥有对象的“克隆”(具有相同内部状态的对象),也许这就是拥有 writeUnshared 的原因,但我不确定那个说实话。
    • @Rollerball 您需要了解您所写内容与您现在所说的意思之间的区别。发送时不会发生创建,因此不会发生值更改。
    猜你喜欢
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多