【问题标题】:Java: how to ensure serializable collectionsJava:如何确保可序列化的集合
【发布时间】:2013-07-23 08:23:07
【问题描述】:

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

因此,如果实现本身是可序列化的(通常是这种情况)并且如果集合中的对象都是可序列化的,则实现 Collection 接口之一的对象是可序列化的。

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

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

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

【问题讨论】:

  • 如果我正确理解您的问题,您可以将您的 List 引用设为 - List&lt;T extends Serializable&gt;。您无需推出自己的界面。
  • 编译器无法检查。每个实现 Serializable 的类都可以包含一个非瞬态、不可序列化的字段,这将导致运行时异常。如果 ArrayList 包含的实际对象是可序列化的,则它可以是可序列化的。如果这真的很重要,请使用单元测试。
  • @RohitJain:您的提议仅保证列表中的对象是可序列化的,但不保证列表实现本身。
  • 你没有抓到我。即使是 ArrayList&lt;Serializable&gt; 也无法序列化。 ArrayList 是可序列化的。它只包含 Serializable 的实例。但是一旦这些包含的对象中的一个包含不可序列化的字段,它就不再是可序列化的。无论添加多少通用边界,运行时都可能出现错误。所以使用测试。
  • 是的。并且当您希望它可序列化时使用不可序列化的集合也是一个错误。通过编写测试来发现错误。

标签: java serialization collections


【解决方案1】:

您本质上要求的是连接两种类型的类型定义:

&lt;type-def&gt; a = null;

您需要用规范替换&lt;type-def&gt;,确保a 引用的对象同时实现SerializableCollection&lt;? extends Serializable&gt;。 Java 语言不支持这样的类型定义。

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

interface SerializableCollection&lt;T extends Serializable&gt; extends Collection&lt;T&gt;, Serializable {}

看起来没问题,直到你尝试这样的事情:

SerializableCollection&lt;String&gt; a = new ArrayList&lt;String&gt;();

但这不会编译。即使ArrayList&lt;String&gt; 实现了Collection&lt;? extends Serializable&gt;Serializable,该类也没有实现SerializableCollection&lt;String&gt;

现在,您可以通过声明一个新类来规避这个问题:

SerializableArrayList&lt;T extends Serializable&gt; extends ArrayList&lt;T&gt; implements SerializableCollection&lt;T&gt; {}

现在您基本上已经组合了您需要的所有内容,并且能够满足最初的要求:

SerializableCollection&lt;String&gt; a = new SerializableArrayList&lt;String&gt;();

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

【讨论】:

  • 谢谢。我想我现在一切都清楚了。正如您和 JB Nizet 所说,我不能相信实现 Serializable-interface 的对象是真正可序列化的(很遗憾)。我认为这就是重点:值得付出努力吗?如果适用于我的情况,我会考虑的。
【解决方案2】:

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

您将如何处理 ListList 而非 Serializable。您需要确保没有对象在对象图中是不可序列化的。并非所有实现Serializable 的对象都可以实际序列化。

【讨论】:

  • 那么有没有办法对此进行编译时检查?
  • interface SerializableCollection&lt;T extends Collection&lt;? extends Serializable&gt;&gt;{} 这样的事情可以做吗?
  • 不能将不是Serializable 的对象的List 添加到SerializableList,因为这个List 没有实现Serializable。当然,我可以添加一个包含一些不可序列化对象的ArrayList(可序列化)——但前提是我将它用作原始类型。如果它是参数化的,编译器应该抱怨这个。
  • 好的,我知道了。使用ArrayList 可以添加导致运行时错误的不可序列化对象。请参阅有关问题的 cmets。
【解决方案3】:

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

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

(例如通过使用 ArrayList(collection) 因为 SerializationUtils 需要 Serializable 接口)

问候, 贡纳尔

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2012-01-04
    相关资源
    最近更新 更多