[英]Deserialization Error in spark using immutable class with java (+ lombok)
我有这个简单的模型类
@Value // lombok - create standard all arg constructor and getters
public class ModelA implements Serializable {
private String word;
private double value;
}
这个简单的测试失败了:
public class SparkSerializationTest {
private SparkSession spark = SparkSession.builder()
.master("local")
.appName("Test")
.getOrCreate();
@Test
public void testSerializationModelA() {
ModelA modelA1 = new ModelA("A1", 12.34);
ModelA modelA2 = new ModelA("A2", 56.78);
Dataset<ModelA> dataset = spark.createDataset(
Arrays.asList(modelA1, modelA2),
Encoders.bean(ModelA.class));
List<ModelA> yo = dataset.collectAsList(); // <== *** failure here ***
assertThat(yo).isEqualTo(Arrays.asList(modelA1, modelA2));
}
}
除了:
java.util.concurrent.ExecutionException: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 24, Column 67: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 24, Column 67: No applicable constructor/method found for zero actual parameters; candidates are: "com.xxx.yyy.ModelA(java.lang.String, double)"
似乎它需要一个零参数构造函数。 但我希望我的模型是不可变的,因此具有完整的 arg 构造函数而没有 setter。 我该怎么做?
只需给它没有任何设置器的无参数构造函数。 它将是可变的,但与提供所有 setter 时相比,它的混乱程度略低。 当您使用Kryo 作为您的解串器时(我认为您已经这样做了),您可以将此构造函数保持为私有。
仍然可以使用空值和无意义的值调用全参数构造函数。 如果您想对对象的有效性强加某种契约,请显式使用验证。 如果您追求的是不变性,则您的成员将不再是使用无参数构造函数的最终成员。
相反,他们创建 vanila 对象并通过 setter 或反射填充它,以确保序列化版本和对象版本之间的名称匹配。 All-args 构造函数会不太可靠并且更难实现。
如果您需要保持不变性,则必须使用自定义对象创建。 请查看Kryo 的自定义对象创建示例:
Registration registration = kryo.register(SomeClass.class); registration.setInstantiator(new ObjectInstantiator<SomeClass>() { public SomeClass newInstance () { return new SomeClass("some constructor arguments", 1234); } });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.