private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
(1)mark:标记表示记录当前pos的位置,可以通过reset恢复到mark位置;
(2)位置position:下一个要被读或写的元素索引。位置会自动随调用get()和put()函数更新
(3)上界limit:缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。
(4)容量capacity:缓冲区能够容纳的数据元素的最大容量。这一容量在缓冲区创建时被设定,就永远不能修改。
一般情况四个属性遵循一下关系:
0<=mark<=position<=limit<=capacity
CharBuffer charBuffer = CharBuffer.allocate(10);
System.out.println("初始limit的值:"+charBuffer.limit());
System.out.println("初始position的值:"+charBuffer.position());
System.out.println("初始capcity的值:"+charBuffer.capacity());
System.out.println("初始mark的值:"+charBuffer.mark());
输出结果:
初始limit的值:10
初始position的值:0
初始capcity的值:10
初始mark的值:
由于ByteBuffer是私有的,只能通过allocate()方法创建,allocate方法是一个静态方法,因此最终创建一个ByteBuffer数组是通过类调用allocate()方法创建,需要传入的参数是容量的大小,底层的具体参数设置如下:
Buffer(int mark, int pos, int lim, int cap) { // package-private
//mark初始值为-1,pos为0,lim与cap初始为传入的长度
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap;
limit(lim);
position(pos);
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}
下面我们在charbuffer数组中存入数据,通过调用它的方法,分析四个属性的变换
public abstract class ByteBuffer
extends Buffer
implements Comparable
ByteBuffer是一个抽象类,继承了Buffer类,实现了Comparable接口,因此ByteBuffer具有Buffer类的方法;即如下方法:
CharBuffer charBuffer = CharBuffer.allocate(10);
String str="hello";
charBuffer.put(str.toCharArray());
System.out.println(charBuffer.length());//剩余容量 5
System.out.println(charBuffer.limit());// 上界 10
System.out.println(charBuffer.capacity());// 最大容量 10
System.out.println(charBuffer.mark());// 暂时未用为 null
System.out.println(charBuffer.position());//下一个要写的位置 5
存储"hello"之后四个属性的变化
public final ByteBuffer put(byte[] src) {
return put(src, 0, src.length);
}
上面通过调用put()方法存储数据,下面我们通过调用filp()方法进入读数据的准备阶段:
CharBuffer charBuffer = CharBuffer.allocate(10);
String str="hello";
charBuffer.put(str.toCharArray());//写如状态
charBuffer.flip();//切换状态,开始准备读的操作,下面四个属性的变化
System.out.println(charBuffer.length());//剩余容量 5
System.out.println(charBuffer.limit());// 上界 5
System.out.println(charBuffer.capacity());// 最大容量 10
System.out.println(charBuffer.mark());// hello
System.out.println(charBuffer.position());//0
属性的变化情况图示:
源码分析:
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
进入读状态,写状态pos的位置为读状态的上界,由图我们也可看出读到下表为5是已经没有数据;读取数据用pos标记,我们需要从头开始读取,因此pos位置重置为0;
CharBuffer charBuffer = CharBuffer.allocate(10);
String str="hello";
charBuffer.put(str.toCharArray());//写如状态
charBuffer.flip();//切换状态,开始准备读的操作,下面四个属性的变化
char c = charBuffer.get();
System.out.println(c);//h
System.out.println(charBuffer.length());//剩余容量 4
System.out.println(charBuffer.limit());// 上界 5
System.out.println(charBuffer.capacity());// 最大容量 10
System.out.println(charBuffer.mark());// ello
System.out.println(charBuffer.position());//1
通过get()读取数据,pos的位置会+1;
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
清空缓冲区,缓冲区中的参数回到初始状态,但里面存储的数据依然存在,处于“被遗忘”状态;
切换读取模式时使用:
可重复读:
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
public final boolean hasRemaining() {
return position < limit;
}
如果pos的值小于lim的值,说明还有数据可读,或者说明还有空间可供存储
通过mark记录当前pos的位置,可以通过reset()恢复到mark的位置
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}