反序列化对象与原始对象的实例相同

Cha*_*son 20 java serialization

当我从类中实例化一个对象时,一个对象被保存在java堆中.当我通过序列化保存对象并稍后反序列化对象时,我是否正确理解该对象现在将具有新的堆地址但仍将是该类的EXACT SAME实例.

Ans*_*man 22

你的问题的答案不能只是一个是或否.分析这个概念是必需的.我会建议你拿一支铅笔和纸,自己动手,记住以下几点.

  • 所有java对象都是在java堆中创建的(除了一些保存在池中但对于你的问题我们现在将跳过它们).
  • 当使用new关键字,反序列化,克隆方法或反射api的newInstance方法创建类的实例时,会保留堆中的新空间并将其分配给对象引用(引用可以是对象的类或其中一个对象类的超类 - 我们现在也可以忽略这个细节).
  • 保存对象时,对象的状态将与其所有嵌套对象一起保存.
  • 反序列化对象时,该对象将在堆中创建一个新条目,该条目不会引用任何对象.

请查看下图,以便在您的上下文中概述上述概念:

在此输入图像描述

所有对象A引用都指向一个堆条目,如果您尝试使用objectB.getObjectA()== objectC.getObjectA()或任何其他此类操作,您将获得true.

情况1当你单独保存对象并反序列化它们时,堆中会发生什么:

在此输入图像描述

现在你可以弄清楚objectBcopy.getObjectA()== objectCcopy.getObjectA()不会返回true,因为复制对象的对象A的引用不再相同.

情况2相反,当您将对象保存在单个文件中并在以后反序列化时,以下是堆中发生的情况:

在此输入图像描述

现在您可以弄清楚objectBcopy.getObjectA()== objectCcopy.getObjectA()现在将为true,因为对象A副本的引用是相同的,但它仍然是对象A的新副本.

一个支持我的扣除的快速计划(案例1和案例2):

public class Test{

    public static void main (String args[]) throws IOException, ClassNotFoundException{
        A a = new A();

        B b = new B();
        b.a = a;

        C c = new C();
        c.a = a;

        System.out.println("b.a == c.a is " + (b.a == c.a));

        // Case 1 - when two diferent files are used to write the objects
        FileOutputStream fout = new FileOutputStream("c:\\b.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(b);
        oos.close();
        fout.close();

        fout = new FileOutputStream("c:\\c.ser");
        oos = new ObjectOutputStream(fout);
        oos.writeObject(c);
        oos.close();
        fout.close();

        FileInputStream fileIn = new FileInputStream("c:\\b.ser");
        ObjectInputStream in = new ObjectInputStream(fileIn);
        B bCopy = (B) in.readObject();
        in.close();
        fileIn.close();

        fileIn = new FileInputStream("c:\\c.ser");
        in = new ObjectInputStream(fileIn);
        C cCopy = (C) in.readObject();
        in.close();
        fileIn.close();
        System.out.println("Case 1 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a));

        // Case 2 - when both the objects are saved in the same file
        fout = new FileOutputStream("c:\\both.ser");
        oos = new ObjectOutputStream(fout);
        oos.writeObject(b);
        oos.writeObject(c);
        oos.close();
        fout.close();


        fileIn = new FileInputStream("c:\\both.ser");
        in = new ObjectInputStream(fileIn);
        bCopy = (B) in.readObject();
        cCopy = (C) in.readObject();
        in.close();
        fileIn.close();
        System.out.println("Case 2 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a));
    }
}

class A implements Serializable{

}

class B implements Serializable{
    A a;
}

class C implements Serializable{
    A a;
}
Run Code Online (Sandbox Code Playgroud)

使用以下输出:

 b.a == c.a is true
 Case 1 - bCopy.a == cCopy.a is false
 Case 2 - bCopy.a == cCopy.a is true
Run Code Online (Sandbox Code Playgroud)