java - 序列化时如何处理依赖字段?

标签 java serialization deserialization

我不明白序列化类时如何处理依赖字段的一般原则。

在许多模式中,字段看起来相互依赖。例如,下面我正在为构造函数中的列表创建一个可观察的包装器。创建时,包装器获取依赖字段并将其包装。

此类在 Gson 和默认 Java 反序列化器中都不会反序列化。

Gson中它调用默认构造函数,它首先建立链接。但后来 Gsondelegate 成员创建了新实例,这破坏了链接,因为 observable 现在引用了过时的对象。

我不明白,如果 Gson 创建者后来放弃它的函数,他们调用默认构造函数是为了什么?他们认为每个类(class)都可以通过直接实地分配吗?

Java 默认序列化也不起作用。他们只是忽略 transient 字段并且它保持为空。未调用构造函数。

我也不明白:如果他们不调用构造函数,那么为什么他们不假设 Serialized 接口(interface)具有一些与构造函数等效的方法,这些方法应该在反序列化之后调用?

package tests;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;

public class Try05 {

    public static class MyList implements Serializable {

        private static final long serialVersionUID = 7048098048856503023L;

        ArrayList<Integer> delegate = new ArrayList<Integer>();
        transient ObservableList<Integer> observable = FXCollections.observableList(delegate);

        public void add(int value) {
            observable.add(value);
        }

        public int sum() {
            int ans = 0;
            for (Integer i : observable) {
                ans += i.intValue();
            }
            return ans;
        }

        @Override
        public String toString() {
            return delegate.toString();
        }

    }

    public static void tryGson() throws JsonIOException, IOException {

        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().serializeNulls().setPrettyPrinting().setVersion(1.0)
                .create();

        MyList list = new MyList();

        list.add(12);
        list.add(13);

        System.out.println(String.format("list = %s, sum = %d", list.toString(), list.sum()));
        System.out.println(String.format("hash = %d", System.identityHashCode(list.delegate)));

        File file = File.createTempFile("list", ".json");

        FileWriter writer = new FileWriter(file);
        gson.toJson(list, writer);
        writer.flush();
        writer.close();

        list = gson.fromJson(new FileReader(file), MyList.class);

        list.add(14);

        System.out.println(String.format("list = %s, sum = %d", list.toString(), list.sum()));
        System.out.println(String.format("hash = %d", System.identityHashCode(list.delegate)));

    }

    public static void tryBuiltin() throws IOException, ClassNotFoundException {

        MyList list = new MyList();

        list.add(12);
        list.add(13);

        System.out.println(String.format("list = %s, sum = %d", list.toString(), list.sum()));
        System.out.println(String.format("hash = %d", System.identityHashCode(list.delegate)));

        File file = File.createTempFile("list", ".json");

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
        out.writeObject(list);
        out.flush();
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        list = (MyList) in.readObject();

        list.add(14);

        System.out.println(String.format("list = %s, sum = %d", list.toString(), list.sum()));
        System.out.println(String.format("hash = %d", System.identityHashCode(list.delegate)));

    }


    public static void main(String[] args) {

        try {

            tryGson();

            tryBuiltin();

        } catch (JsonIOException | IOException | ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }


}

最佳答案

您关于 Serialized 接口(interface)不包含反序列化时调用的方法的声明不正确 - 有;使用默认的 java 序列化,您可以声明一个特殊的方法,该方法将在读取对象时调用。它看起来像这样:

private /* or any other access modifier */ void readObject(ObjectInputStream in) throws IOException {
    // your code here
}

在这种情况下,该方法的内容将如下所示:

in.defaultReadObject(); // invoke default read
observable = FXCollections.observableList(delegate); // initialise observable

有关此方法和其他方法的更多信息,请查看 Serialized 类的规范: http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

关于java - 序列化时如何处理依赖字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22355818/

相关文章:

java - 3.3 到 3.4 之间的 Mule 消息不兼容问题

c# - 数组的反序列化不支持 JSON 反序列化类型

java - 将图像加载到 ImageView JavaFX

java - 数组中整数的总和

c# - 自定义引用循环处理

python - 使用 flask 棉花糖序列化几何

serialization - Rust 数据结构的二进制序列化

c++ - 返回的对象失去属性

c# - 反序列化数组总是为元素返回 null 但适用于属性

java - Hibernate 验证和 Spring 3.x