Java自动字段值序列化

时间:2012-02-17 09:37:15

标签: java serialization field bytebuffer

假设我们有类似结构的java类

public class Person {
    private int height;
    private byte nChildren;
    private int  salary; 

    public byte[] serializeField() {
        ByteBuffer buf = ByteBuffer.allocate(4 + 1 + 4);
        buf.order(ByteOrder.BIG_ENDIAN);
        buf.putInt(height);
        buf.put(nChildren);
        buf.putInt(salary);
        return buf.array(); 
    }

    /*
     * setters and getters
     */
}

是否有可以为任何给定类自动执行serializeField()函数的库?它应该能够维护类中定义的字段的精确顺序,并且可能能够忽略某些字段(如serialVersionUID)。

1 个答案:

答案 0 :(得分:0)

你可以用反射写一个。

如果表现很重要,你可以

  • 传入ByteBuffer以追加以避免创建大量丢弃的缓冲区。

    public void serializeField(ByteBuffer buf) {
        buf.putInt(height);
        buf.put(nChildren);
        buf.putInt(salary);
    }
    
  • 并生成代码(使用反射等)以避免在运行时使用反射。即使用反射生成上面或下一个例子中的代码。

  • 将字段getter和setter映射到ByteBuffer,因此没有序列化/反序列化。

假设您有一个宽度和高度的对象。正如您所看到的,值被更新为ByteBuffer(例如直接或内存映射文件)。这样就没有序列化开销。

class Sized {
    private ByteBuffer buffer;
    private static final int HEIGHT_OFFSET = 0;
    private static final int WIDTH_OFFSET = 4;

    public void setBuffer(ByteBuffer buffer) {this.buffer = buffer; }
    public int getHeight() { return buffer.getInt(HEIGHT_OFFSET); }
    public void setHeight(int height) { buffer.putInt(HEIGHT_OFFSET, height); }
    public int getWidth() { return buffer.getInt(WIDTH_OFFSET); }
    public void setWidth(int width) { buffer.putInt(WIDTH_OFFSET, width); }
}

要处理内存映射数据,您可以使用这样的库。

https://github.com/peter-lawrey/Java-Chronicle

这个库允许您创建任意数量的事件/记录(数十亿),这些事件/记录可以很快更新(但一旦写入就不会增大)。例如每秒数百万条记录,具有亚微秒级延迟。它也可以在进程之间共享。一旦超出主内存,主要限制是硬盘驱动器的速度超过内存使用量。 SSD真的会有所帮助。它有一种模式,你只需启用它就可以直接使用Unsafe类(比ByteBuffer更低级别)。