Java 傻瓜序列化

Java Serialization for Dummies

我仍在从事我已经需要一些帮助的项目:

现在我想了解 Java 中的整个序列化过程是如何工作的,因为不幸的是,我现在并没有真正理解它。

在继续之前,首先,我是一名学生,我不是专业人士。其次,我既不熟悉使用 DB,也不熟悉 XML 或 JSON,所以我只想找到我的方法的解决方案,无论它最终可能多么不优雅,它只是需要工作。因此,如果我只是拒绝使用其他技术的任何建议,请不要感到被冒犯。

这就是我想要的: 将三个不同的 class 对象保存到单独的文件中,但保持对每个对象的向后兼容性。这些对象是设置、统计信息和一个 "database" 对象,其中包含添加到其中的列表中的所有单词。将来我可能会添加更多统计信息或设置,意味着添加新变量,主要是 IntegerPropertyDoubleProperty.

类型

现在的问题是:是否可以加载旧版本保存的文件,然后在此过程中仅使用 null 启动旧版本中未找到的新变量,但保留其余的,因为它已经保存?

我所知道的是,这样做的第一件事就是不要改变 serialVersionUID


另一件事是保存整个模型对象(其中包含前面提到的三个对象),所以我只需要为一个 class 而不是三个实现东西。但是,关于向后兼容性,这将如何工作呢?我的意思是 class 本身不会改变,但它是它们自己的 class 结构中的属性。


最后,我应该采用什么方法?最重要的是,我如何做到这一点并同时保持向后兼容性?我最擅长的是一些具体的例子,而不是简单的理论。

这里有两个示例方法,如果有帮助的话。我已经为每个 class 编写和读取对象提供了方法。

public static void saveModel(Model model, String destination) throws IOException
{
    try 
    {
        fileOutput = new FileOutputStream(destination);
        objectOutput = new ObjectOutputStream(fileOutput);
        objectOutput.writeObject(model);
    }
    catch (IOException e) 
    {
      e.printStackTrace();
    }
    finally
    {
      if (objectOutput != null) 
      try 
      { 
           objectOutput.close(); 
      } 
      catch (IOException e) {}

      if (fileOutput != null) 
      try 
      { 
          fileOutput.close(); 
      } 
      catch (IOException e) {}
    }
}

public static Settings readSettings(String destination) throws IOException, FileNotFoundException
{
    Settings s = null;

    try 
    {
        fileInput = new FileInputStream(destination);
        objectInput = new ObjectInputStream(fileInput);

        Object obj = objectInput.readObject();

        if (obj instanceof Settings) 
        {
            s = (Settings)obj;  
        }
    }
    catch (IOException e) 
    {
        e.printStackTrace();
    }
    catch (ClassNotFoundException e) 
    {
        e.printStackTrace();
    }
    finally 
    {
        if (objectInput != null) try { objectInput.close(); } catch (IOException e) {}
        if (fileInput != null) try { fileInput.close(); } catch (IOException e) {}
    }

    return s;
}

如果您需要更多我当前的代码,请告诉我。

提前致谢!

...你一定有这么高

关于序列化的最佳建议是为了应用程序持久性避免它,特别是如果您的应用程序需要向后兼容性属性。

答案

Is it possible to load old version saved files and then during the process just initiate new variables not found in the old version with just null but keep the rest as it has been saved?

。将使用以前版本的 class 保存的对象反序列化为新版本的 class 仅在以下情况下才有效:

  • class 的完全限定名称未更改(名称和包相同)
  • 之前和现在的class完全一样serialVersionUID;如果其中一个版本缺少它,它将被计算为所有字段 和方法 的 'hash' 并且在不匹配的情况下反序列化将失败。
  • 继承层次结构没有改变class(相同的祖先)
  • class
  • 的新版本中没有删除任何字段
  • 没有字段变成static
  • 没有字段变成transient

I just have to implement stuff for one class instead of three. But how would that work then concerning backward compatibility?

。前提是 ModelModel 所有字段的所有 classes class 本身遵守上述规则。

Finally, what approach should I go for? And most of all, how do I do this and maintaning backward compatibilty at the same time?

可以,只要你能保证以上所有规则永远,你就可以向后兼容了。

我相信你会明白这一点很难保证,尤其是在软件方面。

这就是为什么人们使用比序列化 Java 对象的二进制表示更强大的数据交换格式来实现应用程序持久性。

table 的原始数据可以使用任何东西保存,从 CSV 文件到 JSON 文档,存储为文件或 NoSQL 数据库中的文档。

有关设置/配置,请查看 Java 的 Properties class,它可以在 *.properties*.xml 之间存储和加载属性文件或单独查看 YAML.

最后为了向后兼容,看看FlatBuffers

应用程序持久化领域非常丰富和成熟,欢迎探索。