【问题标题】:Java Automatic Field Value SerializationJava 自动字段值序列化
【发布时间】:2012-02-17 09:37:15
【问题描述】:

假设我们有一个类似结构的 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)。

【问题讨论】:

  • 这不就是你通过标记类Serializable然后向/从对象流写入/读取该对象所得到的吗?字段顺序当然保持不变,可以使用transient 忽略字段。如果您希望它完全像您的 serializeField() 函数那样完成(显式字节顺序,没有关于类的信息),那么您必须自己编写。

标签: java serialization field bytebuffer


【解决方案1】:

你可以用反射写一个。

如果性能很重要,您可以

  • 传入一个 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 更底层)。

【讨论】:

  • 我正在写一篇文章,感觉就像我在重新发明一个轮子。快速检查了 Kryo 和其他人,但无法完成我需要的工作。我似乎不明白你的前两点。您的最后一点不起作用,因为缓冲区的写入将取决于调用方法的顺序。假设 setSalary(int) 在 setHeight(int) 之前被调用。
猜你喜欢
  • 1970-01-01
  • 2012-02-15
  • 2014-08-10
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多