2.3 复制Buffer对象
如前面讨论的那样,我们能够创建管理外部数组数据的Buffer对象。但是Buffer对象不仅能管理外部数组,也能管理其他的buffer对象。当创建一个管理其他buffer对象的buffer对象时,这个buffer对象称为视图Buffer对象。大多数的视图buffer对象都是ByteBuffer对象的视图(参看2.4.3小节)。在陷入Bytebuffer的视图Buffer的细节之前,我们先将目标放在所有buffer类型的共同点上。
视图buffer通常通过调用已创建的buffer对象方法来创建。通过调用已创建的buffer对象的工厂方法来创建视图Buffer,意味着被创建的视图buffer能够访问原始的buffer对象的实现细节。视图buffer将能直接访问数据元素,而不需要调用原始buffer对象的put和get方法,不管它们是存储在数组中还是其他的形式中。如果buffer对象是直接创建于内核中的,视图buffer将拥有跟原始buffer一样高的效率,对于映射buffer视图buffer也一样(映射buffer参见第三章)。
在这一小节中,我们将使用CharBuffer作为例子,其他的基本类型的buffer跟CharBuffer的操作大同小异(其他类型的Buffer参见图2.1)。
public abstract class CharBuffer
extends Buffer implements CharSequence,Comparable{
public abstract CharBuffer duplicate();
public abstract CharBuffer asReadOnlyBuffer();
public abstract CharBuffer slice();
}
Duplicate方法创建一个跟原始buffer一样的buffer对象。两个buffer对象共享同样的数据,拥有同样的容量,但是每个对象拥有各自的position、limit和mark属性。在一个buffer对象中对数据的修改将反映在另外一个buffer对象上。这个副本具有跟原始的buffer对象一样的视图。如果原始的buffer对象是只读的,或者直接分配于内核中,副本将继承这些属性。在2.4节中将分析直接分配与内核中的buffer对象。
注意: Duplicate方法创建的buffer不会复制原始buffer的数据。副本和原始buffer对象将会操作于同样的数据上。 |
原始的buffer对象跟它的副本的关系如图2.12所示。图中的结果是有下面的代码产生的。
CharBuffer buffer=CharBuffer.allocate(8);
buffer.position(3).limit(6).mark().position(5);
buffer.clear();
图2.12 创建buffer的副本
你能通过调用buffer对象的asReadOnlyBuffer方法来生成一个只读的buffer对象。这个对象跟duplicate方法生成的buffer一样,除了这个新建的buffer不容许使用put方法,同时buffer的isReadOnly方法将返回true。试图对只读buffer调用put方法将导致抛出ReadOnlyBufferException异常。
注意: 如果只读的buffer跟一个可写的buffer共享数据,或者拥有一个后备的数组,那么对可写的buffer对象或者后备数组的修改将反映在所有关联的buffer对象上,包括只读buffer对象。 |
对buffer对象进行分割(slice)操作,跟duplicate方法相似,也将创建一个新的buffer对象,但是这个buffer对象将从原始buffer对象的position位置开始,这个buffer对象的容量是原始buffer的剩余数据的数量(limit-position)。这个新创建的buffer对象共享原始的buffer对象的子集。分割的buffer对象将继承原始buffer对象包括只读、开辟位置的属性。图2.13展示了由下面代码产生的分割buffer。
CharBuffer buffer=CharBuffer.allocate(8);
buffer.position(3).limit(5);
CharBuffer sliceBuffer=buffer.slice();
图2.13 分割buffer对象
为了创建一个映射在数组12~20位置(9个数据)的buffer对象,可以使用下面的代码。
char[] myBuffer=new char[100];
CharBuffer cb=CharBuffer.wrap(myBuffer);
cb.position(12).limit(21);
CharBuffer sliced=cb.slice();
更详细关于视图buffer的讨论见2.4.3小节。