【问题标题】:Why doesn't java.util.List implement Serializable?为什么 java.util.List 不实现 Serializable?
【发布时间】:2011-06-23 01:41:06
【问题描述】:

为什么java.util.List 没有实现Serializable 而像LinkedListArraylist 这样的子类可以实现?这似乎不违反继承原则吗?例如,如果我们想通过网络发送 Linkedlist,我们必须这样写:

new ObjectOutputStream(some inputStream).writeObject(some LinkedList);

到目前为止一切顺利,但是在读取另一侧的对象时,我们必须明确地说 LinkedList l = (LinkedList)objectInputStream.readObject(); 而不是 List l = (List)objectInputStream.readObject();。如果我们要将写入功能从LinkedList 更改为ArrayList,我们还必须更改读取部分。让List 实现Serializable 就可以解决问题。

【问题讨论】:

  • 我不认为你的陈述的第二部分是准确的,而不是我有机会尝试它。您遇到了什么样的错误?

标签: java list serialization inheritance collections


【解决方案1】:

List 没有实现Serializable,因为它不是列表的关键要求。无法保证(或不需要)List 的每个可能实现都可以序列化。

LinkedListArrayList 选择这样做,但这是特定于它们的实现的。其他List 实现可能不是Serializable

【讨论】:

  • 在这种情况下,同样的参数可以应用于 LinkedList 以及作为一个非常基本的列表,它不是可序列化的,因为它不是列表的要求。
  • 强制列表的所有实现可序列化和选择一个特定实现可序列化是不同的。
  • LinkedList 是一种实现,开发人员选择为其提供可序列化属性。如果我们按照你的推理,任何类都不应该同时实现两个接口......
【解决方案2】:

List 是一个接口,使其扩展 Serializable 意味着 List 的任何实现都应该是可序列化的。

serializable 属性不是 List 抽象的一部分,因此不应该是实现所必需的。

【讨论】:

    【解决方案3】:

    没有。 LinkedList 始终是一个列表。当你反序列化链表时,由于一个LinkedList是一个List,你可以写

    List l = (List) objectInputStream.readObject();
    

    l 实际上是一个 LinkedList 这个事实并不重要。你想要一个列表,你得到了一个列表。

    【讨论】:

    • 你确定吗?如果将对象强制转换为不可序列化的接口,运行时将如何理解如何反序列化?
    • 转换发生在反序列化之后,因此在这里并不重要 -> 转换到 List 很好
    • 运行时知道如何对对象进行序列化,因为它的序列化字节流包含已序列化对象的类名。 ObjectInputStream 因此创建了这个类的一个实例,并用在序列化对象中找到的数据填充它,然后将它返回给调用者。调用者知道它是一个被序列化的列表,因此将返回的对象转换为一个列表。
    【解决方案4】:

    因为List 也可以由用户特定的子类实现,而实现者可能不一定想要实现Serializable。可序列化也不属于List 的主要职责,因此没有理由将两者联系在一起。

    【讨论】:

      【解决方案5】:

      考虑假设的ThreadList implements List<Thread>,其中包含任何给定时间点的活动线程列表。该实现透明地浏览活动线程并允许轻松访问它们 - 为了您的方便。这样的实现是否应该是可序列化的(忘记Thread 是不可序列化的)?

      由实现接口的人来决定,她的实现是否可以安全地被序列化。 List 太笼统了,基本上是在陈述 *T 类型项目的有序集合。

      【讨论】:

        【解决方案6】:

        您的问题似乎是基于误解。要序列化一个对象,对象(或其类)必须实现Serializable,但您不需要使用Serializable(或某些子类型)类型的表达式来执行此操作。 writeObject 方法的参数类型为Object 而不是Serializable,以及返回类型为readObject(),这是非常有意的。

        但是即使这些参数和返回类型是Serializable,你也不需要知道具体的实现类型:

        ObjectOutputStream stream = ...;
        List myList = ...;
        stream.writeObject((Serializable)myList);
        

        ObjectInputStream stream = ...;
        List myList = (List) stream.readObject();
        

        会像现在一样工作(没有 Serializable 演员表)。

        ObjectInputStream 和 ObjectOutputStream 在调用时根本不关心您的类型,它们只是查看手头的对象及其类。

        【讨论】:

          【解决方案7】:

          如果 List 实现/扩展 Serializable,那么您已经暗示了 List 的所有实现类/子类也是 Serializable 的合同,这并不总是正确的。例如,查看ForwardingListMultimap 的 guava-collections 实现。它不需要在功能上是可序列化的,这只是因为 List 不是可序列化的。

          【讨论】:

            【解决方案8】:

            为什么java.util.List没有实现Serializable ...

            因为并非世界上每个List 实现都必须是Serializable

            在阅读另一边的对象时,我们必须明确地说... 而不是

            List l = (List) objectInputStream.readObject();
            

            你试过了吗?如果你这样做了,我想你会发现它有效。

            【讨论】:

              【解决方案9】:

              List扩展了Collection,它不能实现任何东西,因为它是一个接口......

              【讨论】:

              • 大概OP的意思是List应该扩展Serializable除了Collection,他使用这个词的事实应该在上下文中理解。 .
              猜你喜欢
              • 1970-01-01
              • 2012-06-17
              • 2021-06-09
              • 2010-09-15
              • 2013-05-01
              • 2012-01-28
              • 2012-07-20
              • 2018-07-29
              • 1970-01-01
              相关资源
              最近更新 更多