1

假设我们有一个由节点和指针表示的任意图,如下所示:

class Node
{
    public ValueType data;
    public ArrayList<Node> adj;
}

现在,我想复制它或在磁盘上写入/读取它(AKA 序列化/反序列化)。我也知道可以使用搜索算法+关联数组来完成。而且,事实证明这种方法称为swizzling

这是我的问题:

我听说在 Java 中通过将类声明为 Serializable,这个特性是自动为你提供的。(这对我来说听起来像是一个魔法!)

这个说法正确吗?Java 是否会自动运行 BFS 来遍历图形并调整指针?换句话说,序列化/反序列化是否会为我克隆对象?(具有相同结构但新节点和更新指针的全新对象)

如果是,那么如果在某些情况下我只想复制指针怎么办?如果我想序列化对象只是为了保留原始指针怎么办?

我很欣赏对此的任何评论。:-)

4

2 回答 2

1

我不认为这完全是你的想法,但差不多。Java 中的序列化是一个相当不透明的过程。您真正需要知道的是,假设一个类及其成员的所有类型 implement Serializable,Java 知道如何将其转换为字节流,以及当您使用该流时如何从该流中重新创建对象的实例要求它反序列化。

来自 C++,起初它看起来确实像黑魔法。我对整个过程持怀疑态度,并不真正相信 JVM 会为我处理好它,因为在 C++ 中,它只是对普通对象知之甚少,无法做到这一点。但它实际上非常好,假设您只需要从 Java 访问数据。

基本上,无需担心指针或它在下面使用的算法。你只需告诉它写一个对象,然后再告诉它读回一个对象,你就得到了与以前完全相同的内存结构。

还有一件事:如果您将变量声明为transient,它将不会被保存,您必须自己恢复它。如果您有缓存某些您不想浪费空间的值的字段,或者您不想到处乱放的包含敏感数据的字段,这将非常有用。但是你必须记住自己恢复它。

于 2012-02-29T01:16:29.880 回答
1

我先解决你的最后一个问题。序列化的目的不是克隆内存中的对象图。它将对象图转换为字节流,以执行诸如保存在文件中或通过网络发送之类的操作。反序列化过程可能在不同的计算机上、在不同的时间、在不同的进程中完成,甚至由非 Java 程序完成,因此像以前一样获得对相同对象的引用并不是一个合理的期望。正在保存和稍后恢复的是对象图的结构和内容,而不是内存中的地址。正是由于这个原因,所有对象都可序列化是没有意义的。例如,序列化 aThread不会有用,因为它在程序的当前实例之外没有意义。

自动序列化背后的魔力并不是很复杂。忽略您可以为自己的类编写的自定义序列化方法以精确控制序列化和反序列化行为,是的,系统将有效地遍历对象图以生成字节流。这种遍历通常作为 DFS 完成,而不是 BFS。基本上,您要求 Java 序列化一个对象,并传递对它的引用。该引用将作为对象图的根。从那里,Java 将递归地序列化该对象的字段。当然,它确实会跟踪循环引用并在输出流中写出适当的标记,以便反序列化器能够连接指针并像以前一样重新创建结构。

于 2012-02-29T01:21:04.407 回答