第二章 缓冲区(10)

来源:互联网 发布:剑灵人族刺客捏脸数据 编辑:程序博客网 时间:2024/05/17 23:41

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对象的putget方法,不管它们是存储在数组中还是其他的形式中。如果buffer对象是直接创建于内核中的,视图buffer将拥有跟原始buffer一样高的效率,对于映射buffer视图buffer也一样(映射buffer参见第三章)。

在这一小节中,我们将使用CharBuffer作为例子,其他的基本类型的bufferCharBuffer的操作大同小异(其他类型的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对象共享同样的数据,拥有同样的容量,但是每个对象拥有各自的positionlimitmark属性。在一个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方法,同时bufferisReadOnly方法将返回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小节。