Buffer

275 阅读4分钟

【写在前面】 所谓读源码,三分看代码,七分看注释。英语不好怎么办,我帮你翻译!

package java.nio 
public abstract class Buffer
extends Object

一种指定基本类型的数据的容器。

Buffer是一个线性,有限的指定基本类型的元素序列。除了它的内容,buffer的其他属性还有capacity,limit,position:

  • Capacity是buffer包含元素的个数,buffer的capacity绝不会是个负数,也不会改变。
  • Limit是第一个不能读/写的元素的索引(译者注:内置数组的下标),buffer的limit绝不会是负数,也不可能大于capacity(最多等于)。
  • Position是第一个可以读/写的元素的索引。Buffer的position绝不会是个负数,也不会超过limit(最多等于)。

这个类对应每种基本类型都有一个子类,除了boolean类型。

Transferring data(数据传输)

这个类的每个子类对get和put都定义了两种类型的操作:

  • Relative(相对)操作从当前的position读或写一个或多个元素,然后position会增加传输的元素的数量。如果要求的传输超过了limit,那么一个相对的get操作就会抛出BufferUnderflowException,一个相对的put操作就会抛出 BufferOverflowException,这两种情况下,数据不会传输。(译者注:position也不会改变)。
  • Absolute(绝对)操作采用显式的元素索引(去读或写元素),不会影响到position,如果这个索引超过了limit,那么绝对的get和put操作会抛出一个IndexOutOfBoundsException

数据当然也可以由适当的channel的I/O操作传输进/出一个buffer,在这种情况下,都是属于相对操作的(译者注:也就是会影响position)。

Marking and resetting(标记和重置)

一个buffer的mark(标记)就是在调用reset方法,position会重置为一个位置的索引。Mark不是一直都是定义好了的,但是在定义mark的时候,它绝不会是个负数,也不会大于position。如果mark已经定义好了,当position和limit被调整到比mark小的时候,mark就会被废弃 (译者注:被置为-1)。如果mark还没定义,调用reset方法将会导致InvalidMarkException抛出。

Invariants(不变式,恒成立的)

下面的不变式适用于:mark,position,limit,capacity:

0 <= mark <= position <= limit <= capacity

一个新创建的buffer总是position=0,mark未定义(译者注:值为-1)。初始化的limit可能为0,也可能为其他值,取决于buffer的类型和构造它的方式。新分配的buffer的每个元素都被初始化为0。

Clearing, flipping, and rewinding(清空,翻转,和倒带)

除了一些访问position,limit,capacity值和标记和重置的方法。这个类也在buffers上定义了下列一些操作:

  • clear 让buffer准备好(接收)一个channel读操作或者相对的put操作(产生的)序列:它会设置limit为capacity,position为0。
  • filp 让buffer准备好一个channel写操作或者相对的get操作所需要的序列:它会设置limit为当前position,position为0.
  • rewind 让buffer准备好重新读它已经包含的数据:它会设置limit不变,position为0。

Read-only buffers(只读缓冲区)

所有的buffer都可读,但不是所有buffer都可写。每个buffer的可变方法都被指定为可选操作,当在只读buffer对象上调用这些方法时,会抛出ReadOnlyBufferException。一个只读buffer不允许它的内容被更改,但是它的mark,position,limit是可变的。一个buffer是否只读可以由调用isReadOnly方法确定。

Thread safety(线程安全)

在多线程并发下使用的buffer不是线程安全的。如果一个buffer被超过一个线程使用,那么访问这个buffer就应该进行适当的同步控制。

Invocation chaining(链式调用)

这个类的方法如果没有返回值,那么就会返回(调用这些方法的)buffer对象本身。它允许方法的调用成为链式,举个例子,下列这些语句序列:

b.flip();  
b.position(23);  
b.limit(42);  

可以被替换成单独的,更紧凑的语句:

b.flip().position(23).limit(42);

Since:1.4