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

41
为什么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 将解决这个问题。


2
我认为你的陈述的第二部分不准确,虽然我还没有尝试过。你遇到了什么样的错误? - Jack Leow
9个回答

49

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

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


2
在这种情况下,同样的论点也可以适用于LinkedList,因为它是一个非常基本的列表,不需要序列化,因为这不是列表的要求。 - Swaranga Sarma
13
强制所有列表实现都可序列化,与选择一个特定的实现是可序列化,这两者之间存在差异。 - JB Nizet
1
LinkedList是一种实现,开发人员可以选择赋予可序列化属性。如果我们遵循你的推理,没有类应该同时实现两个接口... - Dunaril

11

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

可序列化属性不是List抽象的一部分,因此不应要求实现。


4

不。LinkedList(链表)始终是List(列表)的一种。当您反序列化链表时,由于LinkedList是List的一种,因此您可以编写

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

事实上,l是一个LinkedList并不重要。你需要的是一个List,而你得到了一个List。


你确定吗?如果你将对象强制转换为不可序列化的接口,运行时如何理解如何反序列化该对象呢? - Dunaril
2
转换发生在反序列化之后,因此在这里并不重要 -> 转换为List就可以了。 - Puce
4
运行时可以序列化对象是因为其序列化的字节流包含被序列化对象的类名。因此,ObjectInputStream会创建这个类的一个实例,并填充它与在序列化对象中找到的数据,然后将其返回给调用者。调用者知道被序列化的是列表,因此将返回的对象转换为List类型。 - JB Nizet

3

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


2
你的问题似乎基于一个误解。要对一个对象进行序列化,该对象(或其类)必须实现 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 调用时完全不关心你的类型,它们只是查看手头的对象及其类。


2
考虑一个假设的实现了 List<Thread> 接口的 ThreadList,它包含了任何时候活跃线程的列表。该实现透明地浏览活跃线程并允许轻松访问它们 - 为您的方便而设计。那么这样的实现是否应该是可序列化的(请忘记 Thread 不可序列化的事实)?
决定实现接口的人需要自己决定她的实现是否可以安全地进行序列化。List 太过于通用,基本上只是陈述“类型为 T 的有序集合”。

0
如果List实现/扩展了Serializable,则您已经暗示了所有List的实现类/子类也是Serializable的合同,但这并不总是正确的。例如看看{{link1:ForwardingListMultimap}}的guava-collections实现。从功能上讲,它不需要是Serializable,而这只有因为List不可序列化才可能实现。

0
为什么java.util.List没有实现Serializable接口...
因为世界上并不是每个List实现都必须是Serializable的。
在读取另一端的对象时,我们必须明确地指定...而不是...
List l = (List) objectInputStream.readObject();

你试过了吗?如果你试一下,我想你会发现它是有效的。


-2

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


3
可以理解为,OP的意思是List应该在实现Collection接口的基础上同时也要扩展Serializable接口。他使用了"implement"这个词应该根据上下文理解。 - davin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接