我需要对一个复杂对象进行序列化,但其组件之一是不可序列化的(第三方图形对象),因此我创建了一个自定义的可序列化版本的这个Graph类,并使用Guava List转换将不可序列化的对象转换为自定义对象。 但是,序列化writeObject仍然失败了。我很想知道原因是什么?我的假设是Lists.transform执行其操作时是惰性的(持有orginal对象的隐藏引用)。
另外,是否有解决此问题的方法?
另外,是否有解决此问题的方法?
Lists.transform()确实像你猜测的那样具有延迟执行的特性。你可以选择以下其中一种方式:
Lists.newArrayList(Lists.transform(...))
或者,如果您想要一个不可变版本,
ImmutableList.copyOf(Lists.transform(...))
然后将生成的列表进行序列化。
Lists.transform() 返回原始列表的转换视图。从 Lists.transform() 的 javadoc 中可以看到:
返回的列表总是实现 Serializable 接口,但只有当 fromList 和 function 都可序列化时,序列化才会成功。
在序列化转换视图时,实际上正在序列化原始列表和函数。在您的情况下,它失败了,因为原始列表不可序列化(因为它包含非可序列化的图形元素)。但也可能失败,因为该函数未实现可序列化接口。
顺便说一下,有一个小技巧可以创建可序列化的函数而不必冗长。不要这样做:
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 pattern
private enum MyFunction implements Function<String, String> {
INSTANCE;
@Override
public String apply(String input) {
return "[" + input + "]";
}
}
fromList
不会被序列化。 - Louis Wasserman