我有一个需要ByteBuffer作为构造函数参数的类。有没有办法避免制作防御性副本,以确保缓冲区在该点之后不会被修改?如何避免制作ByteBuffer的防御副本?
ByteBuffer.isReadOnly()不保证原始所有者不会修改缓冲区。更糟的是,似乎没有办法对ByteBuffer进行子类化。有任何想法吗?
我有一个需要ByteBuffer作为构造函数参数的类。有没有办法避免制作防御性副本,以确保缓冲区在该点之后不会被修改?如何避免制作ByteBuffer的防御副本?
ByteBuffer.isReadOnly()不保证原始所有者不会修改缓冲区。更糟的是,似乎没有办法对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
唯一真正的方法是,如您所说,buf.asReadOnlyBuffer()
,然后将其传递给构造函数。除此之外,没有其他选择,但您可以将内容复制到新的ByteBuffer
,然后通过。
即使构造函数接收到只读缓冲区,也无法保证缓冲区不会被原始所有者(保留写入访问权限)修改。所以你仍然不得不做一个防御性的副本。 – Gili
不避副本,但也许是:
这并不完全回答这个问题,但对于某些用法(例如,如果您主要尝试执行“按合同设计”),它可能足够好,效率更高。对于其他用法,它不起作用,效率可能会低得多。
在你的构造,节省掉字节缓冲区的的hashCode
最终诠释originalBBHashCode = byteBuffer.hashCode();
然后,在您要验证ByteBuffer没有更改的代码中的几个关键位置,验证byteBuffer.hashCode()== originalBBHashCode。如果不是,则抛出异常。坦率地说,我很想引发一个ConcurrentModificationException,因为那是你模仿的行为,但是YMMV。
+1。很好的实践问题。 – helios
听起来像接收者需要的是写入时复制字节缓冲区。 –