【问题标题】:Java interface for manual serialization用于手动序列化的 Java 接口
【发布时间】:2016-05-10 09:30:40
【问题描述】:

我有一些数据结构的实现,这里是scheme

interface Structure {
  //some methods
}

class SomeRealization implements Structure {
  ...
}

class AnotherRealization implements Structure {
  ...
}

我以char array 的形式手动序列化它们,使用FileChannelCharBuffer。是的,我可以通过writeObject 方法做同样的事情,但是nioObjectOutputStream 快。

我想定义 mixin 来保存序列化/反序列化方法,以使项目可扩展,并且因为实现的序列化/反序列化算法不同。像这样的

interface StructureIO {
  void saveStructure(String filename);
  Structure loadStructure(String filename);
}

因此,如果我为实现结构实现此接口,我将需要调用loadStructure(String filename) 方法的实例,这不合适,实际上这很糟糕。

是的,我可以在 Java 8 中将 loadStructure(String filename) 方法定义为静态方法,但它不会给我任何信息,因为静态方法不能被覆盖。

所以如果你有什么想法,请写 在此先感谢 ;)

【问题讨论】:

  • 看到“手动序列化接口”首先想到的是Externalizable...这是一个允许实现类提供手动序列化的接口。
  • @VGR nio 比 Externalizable 更快,这就是为什么我不想使用 Externalizable
  • @VGR 而不是 nioObjectOutputStream 更快
  • 快多少?磁盘 I/O 可能更像是一个瓶颈。即使这确实提高了性能,您是否会经常进行这种加载和保存以需要它?是否值得增加额外的复杂性?
  • @VGR 关于额外的复杂性你是完全正确的,但是如果我需要存储大小为 1,000,000 个元素的 char 数组怎么办?好的,我会做一些测试并回复你:)

标签: java serialization architecture mixins


【解决方案1】:

Java有一个手动序列化的接口:Externalizable

即使 java.nio 更快(这是许多其他 Stack Overflow 讨论的主题),它也不太可能明显更快。磁盘 I/O 可能会成为更大的瓶颈。

即使自定义方法确实可以提高性能,我怀疑您不会经常执行此加载和保存以需要它。出于这些原因,我只会使用 Externalizable,并避免额外的复杂性。

【讨论】:

  • 这并没有解决决策问题:在调用反序列化方法之前要实例化哪个类型?
【解决方案2】:

如果你可以覆盖这个静态方法,你会如何使用它?在调用方法之前必须决定要实例化哪个类,但您需要开始读取文件才能这样做。

我的意思是,你想要的是一种读取文件并创建结构对象的方法:

Structure s = loadStructure(filename);

问题是,这个方法需要知道它可以构建的所有子类,并且需要从文件本身读取它应该构建哪个子类。

因此,你需要一些通用代码开始读取文件,并根据文件中的类型信息调用正确类的静态方法。使用一个对它们都了解的工厂类,并允许子类自己定义静态方法,而不是通过接口强制执行它(无论如何你都不需要)。

【讨论】:

  • 创建公共类并定义我在他的加载方法中加载的结构类型是个坏主意,因为用户在不修改此类代码的情况下无法扩展项目。 Meaby 我理解错了,所以我很抱歉
  • @MikeHerasimov 你理解的没错。但是你不能有一个方法来获取任何文件并返回正确的结构子类的对象而不这样做。在某些时候,您必须有一些通用代码才能做出该决定。公认的答案只是解决通用方法实现中特定于类型的部分,但它不允许您避免该方面。
  • 呃,我现在明白了,你的意思是我需要一些代码来了解结构文件的类型,以便返回用户权限类型 (+1)
  • 我可以简单地存储带有类名或单字节的字符串,它定义了文件保存的类型,但是如何使它全部可扩展又来了一个麻烦
  • @MikeHerasimov 没错。您需要文件中的类型信息,这不应该是存储的问题。我的观点是,您需要代码来读取它并从中选择类型,这就是在多态性发挥作用之前。
【解决方案3】:

如果你不愿意容忍loadStructure——我想你可以通过让对象被创建为未初始化然后用loadStructure初始化它们——那么你将无法强制反序列化作为一部分接口契约。

然而,这不一定是一场灾难,因为首先进行通用反序列化并不一定有意义。当您查看序列化的字节流(或字符,我想,在您的情况下)时,您需要知道它是什么类型才能理解它。因此,不一定需要通用反序列化,您只需编写 MySpecificClass.deserialize(InputSourceType source)(替换为文件名、InputStream 或您认为合适的任何抽象)。

【讨论】:

  • 你需要知道它是什么类型才能理解它——我的意思是准确的,用一种很好的方式:)
  • 你能写一些伪代码或代码方案吗,因为我不明白你是怎么想象的
  • 据我所知,最简单的方法是将未初始化的公共实例添加到两个实现中
  • 宁愿保证他们的创作可能性
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
相关资源
最近更新 更多