简体   繁体   English

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

[英]Java Serialization Problems, while using guava Lists.transform

I had to serialize a complex object, but one of its component was non-serializable ( a third party graph object), so I created a custom serializable version of this Graph class and used Guava List transform to convert the non-serializable object to the custom objects. 我不得不序列化一个复杂的对象,但其中一个组件是不可序列化的(第三方图形对象),所以我创建了这个Graph类的自定义可序列化版本,并使用Guava List转换将非序列化对象转换为自定义对象。 The serialization writeObject still failed. 序列化writeObject仍然失败。 I will be interested to know why? 我有兴趣知道为什么吗? My assumption is that the Lists.transform performs its operation Lazily (Holding an hidden reference to the orginal object.) 我的假设是Lists.transform执行Lazily操作(保持对原始对象的隐藏引用。)

Also is there an workaround for this problem ? 还有解决这个问题的方法吗?

Lists.transform() does perform lazily as you suspected. 你怀疑Lists.transform()确实懒散地执行。 You could do one of 你可以做其中一个

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

or, if you want an immutable version, 或者,如果你想要一个不可变的版本,

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

and then serialize the resulting list. 然后序列化结果列表。

Lists.transform() returns a transformed view of the original list. Lists.transform()返回原始列表的变换视图。 From the Lists.transform() javadoc : 来自Lists.transform() javadoc

The returned list always implements Serializable, but serialization will succeed only when fromList and function are serializable. 返回的列表始终实现Serializable,但只有当fromList和function可序列化时,序列化才会成功。

When serializing the transformed view, you are actually serializing the original list, plus the function. 序列化转换后的视图时,实际上是序列化原始列表和函数。 In your case, it fails because your original list is not serializable (because it contains non-serializable graph elements). 在您的情况下,它失败,因为您的原始列表不可序列化(因为它包含不可序列化的图形元素)。 But it could also fail because the function does not implement serializable. 但它也可能失败,因为该函数不实现可序列化。

BTW, there is a little trick to create serializable functions without the verbosity. 顺便说一句,有一个小技巧来创建可序列化的功能而没有冗长。 Instead of doing: 而不是做:

  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;
  }

You can use the enum singleton pattern, which is a lot less verbose, and gets you serialization for free (since enums are serializable). 你可以使用enum singleton模式,它不那么详细,并且免费获得序列化(因为枚举是可序列化的)。 It also makes sure your Function is a singleton: 它还确保您的Function是一个单例:

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM