为什么 Java 的 nio.ByteBuffer 不可序列化?
Why isn't Java's nio.ByteBuffer serializable?
有时将它与其余数据序列化是有意义的。现在我们必须打开它。
编辑:还有其他可用的选项吗?例如。 Apache commons lang 有 MutableInt,它是原始 int 的轻量级包装器?
为什么真的重要吗?尽管使用直接缓冲区肯定存在潜在问题。
如果您只是偶尔需要这样做,您可以编写自己的 writeObject()
/readObject()
实现来处理序列化。
我的猜测是,由于 ByteBuffer 的内容已经是一个 blob,因此 reading/writing 它们 to/from streams/channels 对于语言的设计者来说并不是一件复杂的事情无需使 ByteBuffers 可序列化。
理论上您可以创建自己的 Externalizable ByteBuffer 实现,例如:
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 种方法(其中一些很棘手),这将是一项艰巨的工作,并且结果将永远不要漂亮
此外,实际的(反)序列化永远不会真正有效,因为没有办法(据我所知?)从 ObjectOutput
中获取 Channel
,这意味着您将需要用老式的方式用中间字节 [4096] 缓冲区或其他东西
我在下一个 post 中回答了自定义序列化的示例:
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;
}
}
有时将它与其余数据序列化是有意义的。现在我们必须打开它。
编辑:还有其他可用的选项吗?例如。 Apache commons lang 有 MutableInt,它是原始 int 的轻量级包装器?
为什么真的重要吗?尽管使用直接缓冲区肯定存在潜在问题。
如果您只是偶尔需要这样做,您可以编写自己的 writeObject()
/readObject()
实现来处理序列化。
我的猜测是,由于 ByteBuffer 的内容已经是一个 blob,因此 reading/writing 它们 to/from streams/channels 对于语言的设计者来说并不是一件复杂的事情无需使 ByteBuffers 可序列化。
理论上您可以创建自己的 Externalizable ByteBuffer 实现,例如:
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 种方法(其中一些很棘手),这将是一项艰巨的工作,并且结果将永远不要漂亮
此外,实际的(反)序列化永远不会真正有效,因为没有办法(据我所知?)从 ObjectOutput
中获取 Channel
,这意味着您将需要用老式的方式用中间字节 [4096] 缓冲区或其他东西
我在下一个 post 中回答了自定义序列化的示例: 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;
}
}