annel的read操作缓冲区,或者是用于相对put操作。
比如向一个接受数据模式的Buffer put5个byte后的示例图:
因为Buffer的设计是读写的位置变量都使用position这个变量,所以如果要从Buffer中读取数据,要切换Buffer到输出数据模式。Buffer提供了flip方法用于这种切换。
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
切换后的效果图:
然后就可以从Buffer中读取数据了。每次读取一个元素,position就会加一,如果position已经等于limit还进行读取,会抛出BufferUnderflowException异常。
可以看出Buffer本身没有一个用于存储模式的变量,模式的切换只是position和limit的变换而已。
flip方法只会把Buffer从接收模式切换到输出模式,如果要从输出模式切换到接收模式,可以使用compact
或者clear
方法,如果数据已经读取完毕或者数据不要了,使用clear
方法,如果已读的数据需要保留,同时需要切换到接收数据模式,使用compat
方法。
// 压缩Buffer,去掉已经被读取的数据
// 压缩后的Buffer处于接收数据模式
public ByteBuffer compact() {
System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
position(remaining());
limit(capacity());
discardMark();
return this;
}
// 清空Buffer,去掉所有数据(没有做清理工作,是指修改位置变量)
// 清空后的Buffer处于接收数据模式
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
总结
- Buffer是Java NIO对缓冲区的抽象
- 除了boolean类型,其他的基本类型都有对应的Buffer实现
- 最常用的Buffer实现是ByteBuffer,具体的实现有HeapByteBuffer和DirectByteBuffer,分别对应Java堆缓冲区与对外内存缓冲区
- HeapByteBuffer是对byte数组的封装,方便使用
- Buffer不是线程安全的
- Buffer有两种模式一种是接收数据模式,一种是输出数据模式。新建的Buffer处于接收数据模式,使用
flip
方法可以切换Buffer到输出数据模式。使用compact
或者clear
方法可以切换到接收数据模式。
参考资料