【问题标题】:Maintaining a Serializable class in Java/Android在 Java/Android 中维护一个可序列化的类
【发布时间】:2011-12-22 14:01:34
【问题描述】:

我正在将一个对象序列化为 SQLiteOpenHelper 中的 blob,如下所示:

final ByteArrayOutputStream bos = new ByteArrayOutputStream();
final ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(value);
out.close();

每个类都定义了自己的永不改变的serialVersionUID。

序列化/反序列化实际上是如何工作的?它是否记得字段的名称以及与之关联的值?如果我继续添加/删除字段,是否有可能修改现有字段的值?

例如,假设我序列化了这个类:

public class Foo implements Serializable {
     private static final long serialVersionUID = 4068188167994381987L;
     String x;
     int y;
}

Where x is "A", and y is 1;

然后我像这样修改类:

public class Foo implements Serializable {
     private static final long serialVersionUID = 4068188167994381987L;
     float f;
     String x;
}

如果我继续添加/删除字段,每次我反序列化Foo x 仍然是“A”吗?

【问题讨论】:

    标签: java android serialization


    【解决方案1】:

    您不能删除字段。请参阅 here at Oracle 以了解对您的 Serializable 类的兼容更改。

    是的,在更改 Foo 类之后,旧的 Foo 的反序列化会将 x 设置为“A”,但是因为您删除了一个字段,所以这不起作用。

    我建议保留旧字段y 并将其标记为@deprecated

    public class Foo implements Serializable {
        private static final long serialVersionUID = 4068188167994381987L;
        String x;
        float f;
        @deprecated int y;
    }
    

    【讨论】:

      【解决方案2】:

      不,如果您更改字段顺序或字段类型,反序列化将无法正常工作。要么导致异常,要么读取不正确的数据。

      这就是为什么建议每次更改时都更改serialVersionUID,以便类的序列化格式发生变化。

      如果您想灵活地更改类内部而不破坏序列化,您应该使用 Externalizable 接口。

      【讨论】:

        【解决方案3】:

        我会使用“神奇的”序列化方法 writeObject 和 readObject 来定义自定义序列化流。这样,您的类的新版本可以读取旧格式,并根据某种转换算法填充新字段(这里,读取 y int 并根据它设置 f 的值)。

        有关序列化“魔术”方法的更多信息,请参见此处: http://thecodersbreakfast.net/index.php?post/2011/05/12/Serialization-and-magic-methods

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-11
          • 1970-01-01
          • 2012-10-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-19
          相关资源
          最近更新 更多