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