Java中的手动对象序列化

时间:2010-02-22 06:31:26

标签: java serialization

我有一个自定义的INIFile类,我编写了读/写包含标题下字段的INI文件。我有几个类,我想使用这个类序列化,但我有点困惑,最好的方法去做。我考虑了两种可能的方法。

方法1:定义像ObjectPersistent这样的接口,强制执行两个方法,如下所示:

public interface ObjectPersistent
{
    public void save(INIFile ini);
    public void load(INIFile ini);
}

然后,每个类都负责使用INIFile类将所有属性输出到文件中。

方法2:通过getter / setter公开需要序列化的类的所有属性,以便可以在一个集中的位置处理保存,如下所示:

public void savePlayer(Player p)
{
    INIFile i = new INIFile(p.getName() + ".ini");
    i.put("general", "name", p.getName());
    i.put("stats", "str", p.getSTR());

    // and so on
}

方法1的最佳部分是并非所有属性都需要暴露,因此封装保持牢固。方法1的不好之处在于,技术上保存并不是玩家会“做”的事情。它还通过传递给方法的ini对象将我绑定到平面文件,因此稍后切换到关系数据库将是一个巨大的痛苦。

方法2的最佳部分是所有I / O都集中在一个位置,实际的保存过程对您完全隐藏。它可以保存到平面文件或数据库。方法2的不好之处在于我必须完全公开类内部成员,以便集中式序列化程序可以从类中获取所有数据。

我希望尽可能简单。我更喜欢在不使用框架的情况下手动执行此操作。我也对使用Java提供的内置序列化不感兴趣。这里有什么我想念的吗?关于什么样的模式最适合这个的任何建议,我将不胜感激。感谢。

3 个答案:

答案 0 :(得分:4)

由于您不希望(出于某种原因)使用Java序列化,因此可以使用XML序列化。最简单的方法是通过XStream

  

XStream是一个简单的库,用于将对象序列化为XML,然后再返回。

如果您确定不想使用任何序列化框架,那么您当然可以使用反射。重要的一点是:

  • getClass().getDeclaredFields()返回班级的所有字段 - 公共和私人
  • field.setAccessible(true) - 通过反射访问私人(或受保护)字段
  • Modifier.isTransient(field.getModifiers())会告诉您该字段是否已使用transient关键字标记 - 即不符合序列化条件。
  • 嵌套对象结构可以用点符号表示 - 例如team.coach.name

所有序列化库都使用反射(或introspection)来实现其目标。

答案 1 :(得分:1)

我会选择方法1。

它可能不是最面向对象的方式,但根据我的经验,它比方法2更简单,更不容易出错并且更易于维护。 如果您对为自己的序列化提供多个实现感到惋惜,可以使用接口来保存和加载方法。

public interface ObjectSerializer
{
    public void writeInt(String key, int value);
    ...
}

public interface ObjectPersistent
{
    public void save(ObjectSerializer serializer);
    public void load(ObjectDeserializer deserializer);
}

您可以改进这些ObjectSerializer / Deserializer接口,以获得足够的方法和参数来涵盖平面文件和数据库案例。

答案 2 :(得分:0)

这是访客模式的工作。