盘一盘 NIO (一)—— Buffer源码解析
Buffer是个啥?
继承关系图
主要属性
// 标记、位置、限制、容量遵守以下不变式: // 0<=mark<=position<=limit<=capacity // 标记是一个位置索引,可以在之后设置位置为标记值再次读写。 private int mark = -1; // 位置,表示缓冲区中正在操作数据的位置。 // 可以把position理解成一个指针,指向的位置就是操作的位置。 private int position = 0; // 界限,表示缓冲区中可以操作数据的大小。 private int limit; // 容量,表示缓冲区中最大存储数据的容量。一旦声明,不可改变。 private int capacity; // 指向缓冲区的地址 long address;
构造方法
// 创建一个具有给定标记、位置、限制和容量的新缓冲区 Buffer(int mark, int pos, int lim, int cap) { // 缓冲区的初始化容量不能小于0 if (cap < 0) throw new IllegalArgumentException("Negative capacity: " + cap); // 初始化缓冲区容量 this.capacity = cap; // 初始化缓冲区限制,设置最新的缓冲区Buffer limit(lim); position(pos); if (mark >= 0) { if (mark > pos) throw new IllegalArgumentException("mark > position: (" + mark + " > " + pos + ")"); this.mark = mark; } }
关键方法解析
position方法:设置当前操作位置
public final Buffer position(int newPosition) { // 当前操作位置不能超过limit大小,不能小于0 if ((newPosition > limit) || (newPosition < 0)) throw new IllegalArgumentException(); position = newPosition; // 如果标记位置大于正在操作位置,那么将mark设置为-1。 if (mark > position) mark = -1; return this; }
limit方法:设置缓冲区限制
public final Buffer limit(int newLimit) { // newLimit大小不能超过缓冲区最大容量capacity,不能小于0 if ((newLimit > capacity) || (newLimit < 0)) throw new IllegalArgumentException(); limit = newLimit; // 正在操作数据的位置不能大于界限 if (position > limit) position = limit; // 如果标记位置大于界限,那么将mark设置为-1。 if (mark > limit) mark = -1; return this; }
reset方法:将缓冲区Buffer的位置position设置为以前临时备忘变量mark存储的位置
public final Buffer reset() { int m = mark; if (m < 0) throw new InvalidMarkException(); position = m; return this; }
public final Buffer clear() { position = 0; // 虽然将limit数值设置为最大容量,只是为了正常使用buffer limit = capacity; mark = -1; return this; }
flip方法: 反转此缓冲区,在进行写完去读的时候使用,说白了,让你开始读的时候从初始位置0开始。
public final Buffer flip() { // 将position置为0,其实就是切换读写模式 limit = position; position = 0; mark = -1; return this; }
rewind方法:重绕此缓冲区,在通道写入或者获取之前调用
public final Buffer rewind() { position = 0; mark = -1; return this; }
remaining方法:返回当前的缓冲区Buffer中剩余元素的数量
public final int remaining() { return limit - position; }
总结