Java 序列化框架(无参数构造函数)

Java 序列化框架(无参数构造函数),java,serialization,deserialization,Java,Serialization,Deserialization,我正在寻找关于基于以下(Java)序列化对象图的最佳方法的一些信息: 如果同一类的两个对象的状态相等,则与true相比,它们必须是二进制相等的(逐位)。(不得依赖于JVM字段顺序) 集合仅使用数组建模(无集合) 所有实例都是不可变的 序列化格式应为byte[]格式,而不是基于文本的格式 我控制着图中的所有类 我不想仅仅为了支持序列化而在类中放置一个空构造函数。 我已经考虑过基于我自己的Objenisis遍历实现一个解决方案,但我的问题似乎并不那么独特。最好先检查任何现有/完整的解决方案 更新

我正在寻找关于基于以下(Java)序列化对象图的最佳方法的一些信息:

  • 如果同一类的两个对象的状态相等,则与true相比,它们必须是二进制相等的(逐位)。(不得依赖于JVM字段顺序)
  • 集合仅使用数组建模(无集合)
  • 所有实例都是不可变的
  • 序列化格式应为byte[]格式,而不是基于文本的格式
  • 我控制着图中的所有类
我不想仅仅为了支持序列化而在类中放置一个空构造函数。 我已经考虑过基于我自己的Objenisis遍历实现一个解决方案,但我的问题似乎并不那么独特。最好先检查任何现有/完整的解决方案

更新的详细信息:

首先,谢谢你的帮助

  • 对象必须根据对象状态序列化为完全相同的位顺序。这很重要,因为二进制内容将进行数字签名。序列化格式的重建将基于对象的状态,而不是存储原始位
  • 不同技术之间的互操作性很重要。我确实看到该软件将来会在ex..Net上运行。序列化格式中没有Java风格
关于不变性的注释:数组的值从参数复制到构造函数的内部字段。不那么重要

致以最良好的祝愿


Niclas Lindberg

关于序列化,需要知道的重要一点是,它不能保证在多个Java版本之间保持一致。它并不是将数据存储在磁盘或任何永久位置的一种方式

在RMI或其他网络协议期间,它在内部用于将类从一个JVM发送到另一个JVM。这些是您应该使用序列化的应用程序类型。如果这描述了您的问题—两个不同JVM之间的短期通信—那么您应该尝试进行序列化

如果您正在寻找一种更永久地存储数据的方法,或者需要这些数据在Java的正向版本中生存,那么您应该找到自己的解决方案。根据您的需求,您应该创建某种方法,自己将每个对象转换为字节流,然后将其读回对象。然后,您将负责确保格式与将来的对象和功能向前兼容


我强烈推荐Joshua Bloch的《高效Java》第11章。

您可以自己编写数据,使用反射或手工编码的方法。我使用的方法是手工代码,除非它们是生成的。(手动编码的性能,以及在代码更改时不必重写代码的便利性)

开发人员经常谈论内置java序列化,但是您可以使用自定义序列化来执行任何您想要的操作,任何您想要的方式

给你一个更详细的答案,这取决于你到底想做什么


顺便说一句:您可以将数据序列化为字节[],但仍然可以在文本编辑器中使其可读/类似文本/可编辑。你所要做的就是使用看起来像文本的二进制格式

您正在寻找可外部化的接口吗?您可以完全控制对象的持久化方式,并且可以使用继承的方法和所有方法(与Serializable使用的私有读/写对象方法不同),使用OO样式来实现这一点。但是,您仍然无法摆脱无参数可访问构造函数的要求。

也许您想熟悉Java可用的序列化框架。这个项目是一个很好的起点,它的名字有误导性:它比较了10多种使用Java序列化数据的方法的性能


看来,最难的限制是不同技术之间的互操作性。我知道谷歌和节俭在这里提供服务。Avro也可能适合。

获得此功能的唯一方法是: A/使用UTF8文本,即XML或JSON,二进制转换为base64(http/XML安全变体)。 B/对所有数据执行UTF8二进制排序。 C/包装内容物,不包括所有未填充的空白区域。
D/对内容进行散列,并在文件中的位置标准位置提供散列。

数组不是不可变的,因此您的要求似乎存在冲突(除非您的意思是除数组之外的所有对象都应该是不可变的)。@ColinD,我想他的意思是,按照惯例,数组设置后不会更改。Java中没有任何东西可以强制执行这种行为。@Peter:Java中没有任何东西可以强制执行数组的不变性,但是除了在集合的实现中,对象数组在Java中真的没有什么位置了。而且集合可以是不可变的。@ColinD,我经常使用数组可能不会让您感到惊讶。虽然没有收藏那么多@彼得:对象数组(原语显然是一个不同的故事)几乎在所有方面都不如集合。在我看来,实际上很少有必要使用它们。