簡體   English   中英

使用帶有 Java 的不可變類的 spark 反序列化錯誤(+ lombok)

[英]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 中創建自定義對象

如果您需要保持不變性,則必須使用自定義對象創建。 請查看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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM