Java序列化问题,同时使用guava Lists.transform

时间:2012-02-23 17:27:54

标签: java serialization guava

我不得不序列化一个复杂的对象,但其中一个组件是不可序列化的(第三方图形对象),所以我创建了这个Graph类的自定义可序列化版本,并使用Guava List转换来转换非可序列化的对象到自定义对象。序列化writeObject仍然失败。我有兴趣知道为什么吗?我的假设是Lists.transform执行其操作Lazily(保持对原始对象的隐藏引用。)

此问题还有解决方法吗?

3 个答案:

答案 0 :(得分:13)

Lists.transform()确实会像您怀疑的那样懒惰地执行。你可以做一个

Lists.newArrayList(Lists.transform(...))

或者,如果你想要一个不可变版本,

ImmutableList.copyOf(Lists.transform(...))

然后序列化结果列表。

答案 1 :(得分:7)

Lists.transform()返回原始列表的转换视图。来自Lists.transform()javadoc

  

返回的列表始终实现Serializable,但序列化   只有当fromList和函数可序列化时才会成功。

序列化转换后的视图时,实际上是序列化原始列表和函数。在您的情况下,它失败,因为您的原始列表不可序列化(因为它包含不可序列化的图形元素)。但它也可能失败,因为该函数没有实现可序列化。

顺便说一句,有一个小技巧来创建可序列化的函数而没有冗长。而不是做:

  private static final class MyFunction extends Function<String, String> implements Serializable {
    private static final MyFunction INSTANCE = new MyFunction();

    @Override
    public String apply(String input) {
      return "[" + input + "]";
    }

    private Object readResolve() {
      return INSTANCE;
    }
    private static final long serialVersionUID = 1;
  }

你可以使用enum singleton模式,这种模式不那么详细,并且可以为 free 进行序列化(因为枚举是可序列化的)。它还确保您的函数是单例:

  // enum singleton pattern
  private enum MyFunction implements Function<String, String> {
    INSTANCE;

    @Override
    public String apply(String input) {
      return "[" + input + "]";
    }
  }

答案 2 :(得分:1)

如果您尝试序列化从Lists#transform返回的列表,则接口List本身可序列化。