【问题标题】:Java: Can I deserialize an object without calling its constructor?Java:我可以反序列化一个对象而不调用它的构造函数吗?
【发布时间】:2013-02-12 20:48:19
【问题描述】:

我有一个四叉树*,我想在多台不同的机器上使用它。调用构造函数(即构建树)需要很长时间。我不想每次需要使用时都构建树。

我正在寻找一种方法将我的树保存在硬盘中,将其发送到每个节点,然后快速将其加载到内存中以便我可以执行查找。

序列化可以帮我解决这个问题吗?我知道我可以序列化树,将其保存到磁盘然后反序列化(这就是我对序列化的所有了解)。据我所知,反序列化步骤需要一个默认构造函数来构建树。由于构建树的计算成本很高,所以这对我没有用。

有没有什么方法可以导入持久化树而不必每次都重新构建它?

*我使用的四叉树基本代码:https://bitbucket.org/utcompling/textgrounder/src/f38150c7f33a/src/main/java/ags/utils/KdTree.java

抱歉,如果这太基本了,它与以下密切相关:https://stackoverflow.com/questions/14701245/how-do-i-perform-kd-tree-lookups-in-hadoop

edit:因此,看起来继承最少的类的无参数构造函数就是将被调用的构造函数。这是我的职位:

抽象 KDTree

QuadTree 扩展 KdTree

SpecialQuadTree(有一个 QuadTree 实例)

现在,我只能在使所有内容都可序列化时才能序列化 SpecialQuadTree(否则我会得到 NotSerizable 或 InvalidClassException 没有有效的构造函数):

抽象 KDTree 实现可序列化

QuadTree 扩展 KdTree 实现 Serializable

SpecialQuadTree 实现 Serializable(有一个 QuadTree 实例)

所以,我想我可以将 Serializable 从 KdTree 中取出,然后给它一个不做任何事情的无参数构造函数?这不容易,我没有写,也不懂KdTree类。我想我可以对它进行子类化,给子类一个不做任何事情的无参数构造函数,并从中继承 QuadTree...

edit:好的,我有一个抽象类 abstract KDTree 实现 Serializable

我由此扩展: QuadTree 扩展 KdTree 实现 Serializable

根据我所有的实验,我需要在两者上实现 Serializable。现在,

public QuadTree() {
    super(2, 1000000);
    System.out.println("QuadTree no-args!");
}

protected KdTree(int dimensions, Integer sizeLimit) {
    System.out.println("KdTree, constructor!");

因为我从来没有看到它打印出来(除了最初的构造......),我想这一切都很好。

【问题讨论】:

  • 你认为序列化和反序列化会比使用标准化的序列化方法(例如 XML/JSON)更有效吗?
  • 过去,我一直使用 JSON 来持久化对象。我现在遇到的问题是我不知道如何编写将我的对象转换为 JSON 的方法。
  • 我建议看看 Google Protocol buf
  • @kabram 有趣的建议。我会仔细看看的。还有更具体的提示吗?
  • 应该有大量的 XML 和 JSON 编组(您所指的过程)往返于 JAVA。例如JAXB:en.wikipedia.org/wiki/JAXB

标签: java serialization


【解决方案1】:

当一个对象在 Java 中反序列化时,只会调用一些无参数的构造函数(参见 this post)。

最简单的方法是让所有涉及的类Serializable。那么你的任何构造函数都不会被调用。如果你不能这样做,请确保你的 Serializablehave access to the no-args constructor of the first non-Serializable class

如果是在您的控制之下的非Serializable 基类,您可以将昂贵的逻辑移动到不同的构造函数(比如说,使用虚拟的boolean 参数)并提供一个简单的无参数构造函数那什么也没做。然后你的所有字段在反序列化后都会在那里,没有计算开销。

信息的最终来源是the serialization spec

【讨论】:

    【解决方案2】:

    据我所知,反序列化步骤需要一个默认构造函数来构建树

    如果您正在研究 Java 对象序列化,则不会。

    看起来继承最少的类的无参数构造函数将被调用。

    没有。调用最近的 non-serializable 基类的无参数构造函数。

    我想我可以将 Serializable 从 KdTree 中取出,然后给它一个不做任何事情的无参数构造函数?

    为什么?别管它。

    【讨论】:

    • 好的。我是新手,它真的只是在我所有的类上“实现 Serializable”,然后 Java 就解决了吗?
    • 将调用最派生的非Serializable 类的默认构造函数(Externalizable 的规则不同,但奇数不同)。
    • 请注意,“默认构造函数”是 Java 为您创建的 no-args 构造函数,如果您的类没有定义构造函数。所以我们可能在谈论 no-args 构造函数,而不是默认构造函数。
    • @rcompton 控制什么?如果您的类是可序列化的,则在反序列化期间将调用 none 的构造函数。
    • @EJP 我不清楚“将调用最衍生的非可序列化类的默认构造函数”是我想要弄清楚的。
    【解决方案3】:

    如果您使用的是 Jackson,是否拥有一个自定义反序列化器并附加到您尝试反序列化的类?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      • 1970-01-01
      • 2018-07-06
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多