问题 Java:如何确保可序列化的集合


在Java中,Collection-interfaces不会扩展Serializable,原因有很多。此外,这些接口的大多数常见实现都实现了Serializable。

因此,实现其中一个Collection-interfaces的对象是可序列化的,如果实现本身是可序列化的(通常是这种情况)  如果集合中的对象都是可序列化的。

但我怎样才能确保满足这两个条件?我不想遇到运行时错误,因为编译器可以检查这些条件。我正在考虑一些明显的界面(展示List-interface):

public interface SerializableList<T extends Serializable> extends Serializable, List<T> {}

我想知道是否没有其他人面临这个问题,并提出了这个简单的解决方案。到目前为止,我无法找到任何解决方案甚至讨论,这让我怀疑我的想法。


7929
2017-07-23 08:23


起源

你可以做你的 List 参考 - List<T extends Serializable>,如果我正确理解你的问题。您不需要推出自己的界面。 - Rohit Jain
编译器无法检查。每个实现Serializable的类都可能包含一个非瞬态的,不可序列化的字段,这会导致运行时异常。如果ArrayList <Object>包含的实际对象是可序列化的,则它可以是可序列化的。如果这非常重要,请使用单元测试。 - JB Nizet
@RohitJain:您的提案只保证列表中的对象是可序列化的,而不是List-implementation本身。 - MrD
你没有抓住我。即使是 ArrayList<Serializable> 无法序列化。 ArrayList是Serializable。它仅包含Serializable的实例。但是,只要其中一个包含的对象包含不可序列化的字段,它就不再可序列化了。无论添加的通用边界数量是多少,都可能在运行时出错。所以使用测试。 - JB Nizet
是。当你想要它可序列化时使用不可序列化的集合也是一个bug。通过编写测试来捕获错误。 - JB Nizet


答案:


你基本上要求的是一个连接两种类型的类型定义:

<type-def> a = null;

你需要的是替代 <type-def> 使用规范,确保引用的对象 a 实现两者 Serializable 以及 Collection<? extends Serializable>。 Java语言不支持这种类型定义。

正如您已经写过的,最明显的解决方案可能是声明您自己的接口,加入这两个其他接口:

interface SerializableCollection<T extends Serializable> extends Collection<T>, Serializable {}

似乎没问题,直到你尝试这样的事情:

SerializableCollection<String> a = new ArrayList<String>();

然而,这不会编译。即使 ArrayList<String> 实现两者 Collection<? extends Serializable> 和 Serializable,该类没有实现 SerializableCollection<String>

现在,如果你愿意的话,你可以通过声明一个新类来规避这个问题:

SerializableArrayList<T extends Serializable> extends ArrayList<T> implements SerializableCollection<T> {}

现在,您已基本结合了所需的一切,并且能够满足原始要求:

SerializableCollection<String> a = new SerializableArrayList<String>();

值得努力吗?在你的情况下,你必须决定,但我会说不。我的论点是,自从 Serializable marker只是一个非正式的“标签”,确保您的集合及其内容实现 Serializable 仍然不保证集合及其内容实际上 能够 被序列化。


6
2017-07-23 09:18



谢谢。我觉得现在一切都很清楚。正如你和JB Nizet所说,我不能依赖那些实现的对象 Serializable-interface是可序列化的(很遗憾)。我认为这是重点:值得努力吗?如果它适用于我的情况,我会考虑它。 - MrD


Serializable 不是一个很棒的界面。它应该是一个注释,如果它们在实施时可用。

你会怎么处理一个 List 一个 List 没有的东西 Serializable。您需要确保没有对象在对象图中传递下来是不可序列化的。并非所有实现的对象 Serializable 实际上可以序列化。


6
2017-07-23 08:38



那么有没有办法对其进行编译时检查? - Narendra Pathai
interface SerializableCollection<T extends Collection<? extends Serializable>>{} 可以这样做吗? - Narendra Pathai
一个 List 不是的对象 Serializable 无法添加到 SerializableList 从此 List 没有实现 Serializable。当然,我可以添加一个 ArrayList (可序列化)包含一些不可序列化的对象 - 但仅当我将其用作原始类型时。如果它是参数化的,编译器应该抱怨这一点。 - MrD
好的,我现在明白了。同 ArrayList 可以添加导致运行时错误的不可序列化对象。请参阅有关该问题的评论。 - MrD


克隆集合和包含对象的方法是

import org.apache.commons.lang3.SerializationUtils;
...
ClonedArrayList = SerializationUtils.deserialize(SerializationUtils.serialize(OriginalArrayList))

(例如,通过使用ArrayList <Type>(集合),因为SerializationUtils需要Serializable接口)

问候, 贡纳尔


0
2018-01-11 14:53