【问题标题】:If my class implements Serializable, do I have to implement it in its subclasses?如果我的类实现了 Serializable,我是否必须在其子类中实现它?
【发布时间】:2012-02-26 21:20:39
【问题描述】:

如果我有 B 扩展 A...并且 A 实现了 Serializable,我是否必须写“B 实现 Serializable”?

我认为没有,但我想确认一下...

另外,如果我将序列化 id 放入 A... 我还需要在 B 中放入一个吗? A 中的序列化 id 是否应该受到保护(不是私有的)?

【问题讨论】:

  • 听起来不是很刻薄,但是尝试这个比你写这个问题花费的时间更少。
  • 听起来不是很刻薄,但如果能始终如一地听取建议,这将是一个非常非常小的网站。

标签: java serializable


【解决方案1】:

是的。子类不需要显式标记为可序列化。

并且,将 id 标记为 protected 就可以了(从编译器的角度来看)。

但是,作为一种好的做法,每个班级都应该有自己的私人serialVersionUID

【讨论】:

  • 谢谢,知道如何摆脱关于未声明序列版本 id 的黄色日食警告吗?
  • 更健壮的方法是定义为private static final
  • 为了清晰起见,我仍然认为在子类上实现 Serializable 会很好。就像 ArrayList 在实现 List 的同时扩展已经实现 List 的 AbstractList 一样。
  • 你应该在serialVersionUID上使用private修饰符。
  • 澄清一下...是serialVersionUID 还是serialVersionUid?我们这里都有。
【解决方案2】:

您不必明确地将派生标记为可序列化,它将被继承。但是,来自父级的 serialVersionUID 虽然是继承的,但不会被序列化过程使用。如果您不向子项添加 serialVersionUID,则会生成一个。

见下文:

public class A implements Serializable {
    protected static final long serialVersionUID = 1L;
}

public class B extends A {
}

public class Main {

    public static void main(String[] args){

        A a = new A();
        B b = new B();

        Class aClass = a.getClass();
        Class bClass = b.getClass();

        long aUid = ObjectStreamClass.lookup(aClass).getSerialVersionUID();
        long bUid = ObjectStreamClass.lookup(bClass).getSerialVersionUID();

        System.out.printf("serialVersionUID:\n");
        System.out.printf("b inherited from a: %d\n", b.serialVersionUID);
        System.out.printf("a used by serialization: %d\n",aUid);
        System.out.printf("b used by serialization: %d\n",bUid);
    }

}

输出:

serialVersionUID:

b 继承自 a: 1

序列化使用的a:1

序列化使用的b:-3675232183873847366

【讨论】:

    【解决方案3】:

    我同意@azodious 的回答,子类继承父类的可序列化属性,但您必须明确声明 serialVersionUID

    来自 Java 文档: https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

    强烈建议显式 serialVersionUID 声明尽可能使用 private 修饰符,因为这样 声明仅适用于立即声明 class--serialVersionUID 字段不能用作继承的成员。

    【讨论】:

      【解决方案4】:

      从编译器的角度来看,将 id 标记为受保护就足够了。然而,理论上,Serializable 类上的 serialVersionUID 字段的意义在于在反序列化时轻松区分该类的“版本”——以明确表示何时可以将给定对象反序列化为所提供的实例类(如果serialVersionUIDs 不同,则抛出异常)。如果您希望能够清楚地跟踪对象的版本和性质,请在每个子类上声明 serialVersionUID

      【讨论】:

      • 我认为 serialVersionUIDs 是为 JVM 声明的以识别类中的更改。并且 JVM 可以从基类中获取它,所以它不应该有任何区别。
      • 嗯,是的,但我的意思是,不要将 serialVersionUID 视为您想要摆脱的烦恼。了解它存在的原因并适当对待它。
      • 是的,但是我们可以有两个具有相同serialVersionUID 的不同类。如果它是一个没有显式扩展任何类的简单类,那么它应该是强制性的。
      • 我的想法是如果我尝试用新修改的类加载旧文件将不兼容......所以我永远不会改变类......(这相对简单类..我只是有一个我正在序列化的列表)......所以为了安全起见,我放了一堆字符串和整数和布尔字段,并将它们称为“reserved1,2等”。 ..在不太可能的情况下,我将来需要将更多数据附加到类中......但是文件仍然是完全相同的格式
      【解决方案5】:

      不,因为 B 已经通过其基类 A 实现了它。这就是继承的全部意义。

      【讨论】:

        【解决方案6】:

        如果 Java 对象的类或其任何超类实现了 java.io.Serializable 接口或其子接口 java.io.Externalizable,则它是可序列化的。

        您可以查看官方文档并在此处找到: https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html

        【讨论】:

          猜你喜欢
          • 2013-10-19
          • 2019-06-30
          • 1970-01-01
          • 2011-10-26
          • 2012-03-05
          • 1970-01-01
          • 2020-07-05
          • 2021-06-19
          相关资源
          最近更新 更多