Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区。注意:Buffer是非线程安全类。capacity一旦初始化后就不会改变,其值一直为常量。在使用中我们一般使用Buffer的抽象子类ByteBuffer.allocate()方法,实际上是生成ByteArrayBuffer类。
(1)Buffer中定义的变量含义
/** * UNSET_MARK
means the mark has not been set. */
static final int UNSET_MARK = -1;
/** * The capacity of this buffer, which never changes. */
final int capacity;
/** * limit - 1
is the last element that can be read or written. * Limit must be no less than zero and no greater than capacity
. */
int limit;
/** * Mark is where position will be set when reset()
is called. * Mark is not set by default. Mark is always no less than zero and no * greater than position
. */
int mark = UNSET_MARK;
/** * The current position of this buffer. Position is always no less than zero * and no greater than limit
. */
int position = 0;
/** * The log base 2 of the element size of this buffer. Each typed subclass * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this * value. The value is used by JNI code in frameworks/base/ to avoid the * need for costly 'instanceof' tests. */
final int _elementSizeShift;
/** * For direct buffers, the effective address of the data; zero otherwise. * This is set in the constructor. */
final long effectiveDirectAddress;
(2)clear()方法用于写模式,其作用为清空Buffer中的内容,所谓清空是指写上限与Buffer的真实容量相同,即limit==capacity,同时将当前写位置置为最前端下标为0处。代码如下:
/** * UNSET_MARK
means the mark has not been set. */
static final int UNSET_MARK = -1;
/** * Clears this buffer. *
* While the content of this buffer is not changed, the following internal * changes take place: the current position is reset back to the start of * the buffer, the value of the buffer limit is made equal to the capacity * and mark is cleared. * *@return this buffer. */
public final Buffer clear() {
position = 0; //设置当前下标为0
mark = UNSET_MARK; //取消标记
limit = capacity; //设置写越界位置与和Buffer容量相同
return this;
}
(3)reset()方法和clear()方法一样用于写模式,区别是reset()的作用是丢弃mark位置以后的数据,重新从mark位置开始写入,且mark不能未设置;而clear是从0位置开始重新写入。
/** * Resets the position of this buffer to the mark
. * *@return this buffer. *@throws InvalidMarkException * if the mark is not set. */
public final Buffer reset() {
if (mark == UNSET_MARK) {
throw new InvalidMarkException("Mark not set");
}
position = mark;
return this;
}
(4)rewind()在读写模式下都可用,它单纯的将当前位置置0,同时取消mark标记,仅此而已;也就是说写模式下limit仍保持与Buffer容量相同,只是重头写而已;读模式下limit仍然与rewind()调用之前相同,也就是为flip()调用之前写模式下的position的最后位置,flip()调用后此位置变为了读模式的limit位置,即越界位置,代码如下:
/** * Rewinds this buffer. *
* The position is set to zero, and the mark is cleared. The content of this * buffer is not changed. * *@return this buffer. */
public final Buffer rewind() {
position = 0;
mark = UNSET_MARK;
return this;
}
(5)flip()函数的作用是将写模式转变为读模式,即将写模式下的Buffer中内容的最后位置变为读模式下的limit位置,作为读越界位置,同时将当前读位置置为0,表示转换后重头开始读,同时再消除写模式下的mark标记,代码如下
/** * Flips this buffer. *
* The limit is set to the current position, then the position is set to * zero, and the mark is cleared. *
* The content of this buffer is not changed. * *@return this buffer. */
public final Buffer flip() {
limit = position;
position = 0;
mark = UNSET_MARK;
return this;
}
(6)remaining()仅在读模式下使用,用来获取还未读出的字节数。
/** * Returns the number of remaining elements in this buffer, that is * {@code limit - position}. * *@return the number of remaining elements in this buffer. */
public final int remaining() {
return limit - position;
}
(7)Buffer的抽象子类ByteBuffer的compact()方法也蛮重要的。compact()的作用是压缩数据。比如当前EOF是6,当前指针指向2(即0,1的数据已经写出了,没用了),那么compact方法将把2,3,4,5的数据挪到0,1,2,3的位置,然后指针指向4的位置。这样的意思是,从4的位置接着再写入数据。
/**
* Compacts this byte buffer.
*
* The remaining bytes will be moved to the head of the
* buffer, starting from position zero. Then the position is set to
* {@code remaining()}; the limit is set to capacity; the mark is
* cleared.
*
* @return {@code this}
* @throws ReadOnlyBufferException
* if no changes may be made to the contents of this buffer.
*/
public abstract ByteBuffer compact();