为什么Java的nio.ByteBuffer不能序列化?

时间:2015-03-27 05:23:47

标签: java serialization

有时将其余的数据序列化是有意义的。现在我们必须解开它。

编辑:还有其他选项吗?例如。 Apache commons lang有MutableInt,它是原始int的轻量级包装器吗?

3 个答案:

答案 0 :(得分:2)

我在下一篇文章中回答了自定义序列化的示例: How to serialize ByteBuffer

基本上,关键是ByteBuffer是字节数组的包装器,所以它没有意义来序列化它(相反,你应该序列化byte [])。 万一你需要序列化ByteBuffer然后......做类似

的事情
public class NetByteBuffer implements java.io.Serializable {
    private static final long serialVersionUID = -2831273345165209113L;

    //serializable property
    String anotherProperty;

    // mark as transient so this is not serialized by default
    transient ByteBuffer data;

    public NetByteBuffer(String anotherProperty, ByteBuffer data) {
        this.data = data;
        this.anotherProperty = anotherProperty;
    }

    public ByteBuffer getData() {
        return this.data;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        // write default properties
        out.defaultWriteObject();
        // write buffer capacity and data
        out.writeInt(data.capacity());
        out.write(data.array());

    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        //read default properties
        in.defaultReadObject();

        //read buffer data and wrap with ByteBuffer
        int bufferSize = in.readInt();
        byte[] buffer = new byte[bufferSize];
        in.read(buffer, 0, bufferSize);
        this.data = ByteBuffer.wrap(buffer, 0, bufferSize);
    }

    public String getAnotherProperty() {
        return anotherProperty;
    }

}

答案 1 :(得分:1)

为什么真的重要?虽然使用直接缓冲区时肯定存在潜在的问题。

如果您需要偶尔执行此操作,则可以编写自己的writeObject() / readObject()实现来处理序列化。

答案 2 :(得分:1)

我的猜测是,因为ByteBuffer的内容已经是一个blob,所以从流/通道读取/写入它们并不是一件复杂的事情,语言的设计者认为没有必要使ByteBuffers可序列化。 / p>

理论上你可以创建自己的Externalizable ByteBuffer impl,例如:

package java.nio; //has to be in java.nio pkg, _get() and _put and pkg-private

public class SerializableByteBuffer extends ByteBuffer implements Externalizable {
    private ByteBuffer theActualBuffer;

    public SerializableByteBuffer(ByteBuffer theActualBuffer) {
        super(0, 0, 1, 1);
        this.theActualBuffer = theActualBuffer;
    }

    // these 2 are package private. this was obviously not designed to be extended

    @Override
    byte _get(int i) {
        return theActualBuffer._get(i);
    }

    @Override
    void _put(int i, byte b) {
        theActualBuffer._put(i, b);
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        //write length + type of underlying buffer (enum?) + contents
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        //read length and type of buffer, instantiate buffer of correct type, read contents into buffer
    }

    //delegate all methods. this is going to be a lot of work as some return buffer copies
}

但是鉴于您必须将它放在java.nio包中,并正确委托~20种方法(其中一些方法很棘手),这将是一项艰苦的工作,结果将是永远不会漂亮。

另外,实际的(de)序列化永远不会真正有效,因为从Channel得到ObjectOutput没有办法(我知道?),这意味着你& #39;我需要用老式的方式用中间字节[4096]缓冲区或其他东西

来做