我有一个类,它以ByteBuffer作为构造函数参数。 是否有一种方法可以避免进行防御性复制,以确保在此过程之后不修改缓冲区?
ByteBuffer.isReadOnly()不能保证原始所有者不修改缓冲区。 更糟糕的是,似乎没有一种方法可以对ByteBuffer进行子类化。 有什么想法吗?
我有一个类,它以ByteBuffer作为构造函数参数。 是否有一种方法可以避免进行防御性复制,以确保在此过程之后不修改缓冲区?
ByteBuffer.isReadOnly()不能保证原始所有者不修改缓冲区。 更糟糕的是,似乎没有一种方法可以对ByteBuffer进行子类化。 有什么想法吗?
buf.asReadOnlyBuffer()
,然后将其传递给构造函数。除此之外别无选择,虽然你也可以将内容复制到一个新的ByteBuffer
中,然后再传递给构造函数。目前我所能做到的最好程度如下:
/**
* Helper functions for java.nio.Buffer.
* <p/>
* @author Gili Tzabari
*/
public final class Buffers
{
/**
* Returns a ByteBuffer that is identical but distinct from the original buffer.
* <p/>
* @param original the buffer to copy
* @return an independent copy of original
* @throws NullPointerException if original is null
*/
public static ByteBuffer clone(ByteBuffer original)
{
Preconditions.checkNotNull(original, "original may not be null");
ByteBuffer result = ByteBuffer.allocate(original.capacity());
ByteBuffer source = original.duplicate();
source.rewind();
result.put(source);
try
{
source.reset();
result.position(source.position());
result.mark();
}
catch (InvalidMarkException unused)
{
// Mark is unset, ignore.
}
result.position(original.position());
result.limit(original.limit());
return result;
}
/**
* Returns an array representation of a buffer. The returned buffer may, or may not, be tied to
* the underlying buffer's contents (so it should not be modified).
* <p/>
* @param buffer the buffer
* @return the remaining bytes
*/
public static byte[] toArray(ByteBuffer buffer)
{
if (buffer.hasArray() && !buffer.isReadOnly() && buffer.position() == 0
&& buffer.remaining() == buffer.limit())
{
return buffer.array();
}
ByteBuffer copy = buffer.duplicate();
byte[] result = new byte[copy.remaining()];
copy.get(result);
return result;
}
/**
* Prevent construction.
*/
private Buffers()
{
}
}
我也向 Oracle 提交了一个功能请求: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7130631
不避免复制,但也许可以:
这并不能完全回答问题,但是对于某些用例(例如,如果您主要想强制实施“契约设计”),它可能足够好并且更有效率。对于其他用例,它将不起作用并且可能效率远低于预期。
在构造函数中,保存 ByteBuffer 的 hashCode:
final int originalBBHashCode = byteBuffer.hashCode();
然后,在代码的几个关键位置,您想要验证 ByteBuffer 是否已更改,请验证 byteBuffer.hashCode() == originalBBHashCode。如果不是,则抛出异常。坦白地说,我会倾向于抛出 ConcurrentModificationException,因为这是您所模拟的行为,但请自行决定。