java 使用 Kryo(自定义序列化程序)序列化对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7909572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:57:28  来源:igfitidea点击:

Serialization of an object with Kryo (Custom Serializer)

javaserializationkryo

提问by user697111

I have an object which contains an array of objects. I would like to

我有一个包含对象数组的对象。我想

  • A) store this array of objects in the same file

  • B) use custom serialization for those objects.

  • A) 将此对象数组存储在同一个文件中

  • B) 对这些对象使用自定义序列化。

For example, I have a Map object which has Tile[][] array. I can do Ints just fine, but confused on how to do objects:

例如,我有一个 Map 对象,它具有 Tile[][] 数组。我可以很好地做 Int,但对如何做对象感到困惑:

    kryo.register(Map.class, new SimpleSerializer<Map>() {
        public void write(ByteBuffer buffer, Map map) {

            buffer.putInt(map.getId());
            System.out.println("Putting: " + map.getId());


        }

        public Map read(ByteBuffer buffer) {
            int id = buffer.getInt();
            System.out.println("Getting: " + id);

            Map map = new Map(id, null, 0, 0, 0, 0);

            return (map);
        }
    });

回答by NateS

I can tell from your example that you are using Kryo v1. I suggest using Kryo v2.

我可以从您的示例中看出您使用的是 Kryo v1。我建议使用 Kryo v2。

You can set a serializer for Map, like you have, and then serialize each key and value. To serialize each object, either write the data using the Output class and read using the Input class, or call methods on the Kryo instance to have it handle the objects.

您可以像您一样为 Map 设置一个序列化程序,然后序列化每个键和值。要序列化每个对象,请使用 Output 类写入数据并使用 Input 类读取数据,或者调用 Kryo 实例上的方法以使其处理对象。

It would be easier to use the built in MapSerializer. You only need to customize serialization of your Tile objects. You can have them extend KryoSerializable or you can register a Serializer. Here is an example...

使用内置的 MapSerializer 会更容易。您只需要自定义 Tile 对象的序列化。您可以让它们扩展 KryoSerializable,或者您可以注册一个序列化程序。这是一个例子...

public class Tile implements KryoSerializable {
    int x, y;
    Object something;

    public void write (Kryo kryo, Output output) {
        output.writeInt(x);
        output.writeInt(y);
        kryo.writeClassAndObject(output, something);
    }

    public void read (Kryo kryo, Input input) {
        x = input.readInt();
        y = input.readInt();
        something = kryo.readClassAndObject(input);
    }
}

Here is another example, using a Serializer instead of KryoSerializable:

这是另一个示例,使用 Serializer 而不是 KryoSerializable:

public class Tile {
    int x, y;
    Object something;
}

kryo.register(Tile.class, new Serializer<Tile>() {
    public void write (Kryo kryo, Output output, Tile object) {
        output.writeInt(object.x);
        output.writeInt(object.y);
        kryo.writeClassAndObject(output, object);
    }

    public Tile read (Kryo kryo, Input input, Class<Tile> type) {
        Tile tile = new Tile();
        kryo.reference(tile); // Only necessary if Kryo#setReferences is true AND Tile#something could reference this tile.
        tile.x = input.readInt();
        tile.y = input.readInt();
        tile.something = kryo.readClassAndObject(input);
        return tile;
    }
});

This is slightly more complicated in the read method because of the call to Kryo#reference before you use the Kryo instance to deserialize child objects. This can be omitted if not using references at all, or if you know that the "something" object cannot possibly reference the tile we have just created. If you were only using Input to read data, you wouldn't need to call Kryo#reference.

这在 read 方法中稍微复杂一些,因为在使用 Kryo 实例反序列化子对象之前调用了 Kryo#reference。如果根本不使用引用,或者如果您知道“某物”对象不可能引用我们刚刚创建的图块,则可以省略此项。如果您仅使用 Input 读取数据,则无需调用 Kryo#reference。