在解释以上方法之前我们需要了解ByteBuffer的几个参数:
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;//标记位置,reset时需要
private int position = 0;//当前读取
private int limit;//读取的最大位置
private int capacity;//buffer的容量
下面通过一个最简单的代码来解释,各个过程中上面参数的变化
//初始化一个长度为48的buffer
ByteBuffer buffer = ByteBuffer.allocate(48);
此时 postion:0,limit48,mark:-1,capacity:48。下面的过程主要是postion、limit、mark会变化,capacity是容量不会变化。
//将数据写入buffer
buffer.put("123456".getBytes());
写入后ByteBuffer的参数变化如下图:
此时只有postion发生了变化,变成了6,因为我们写了6个字符。我们写入的数据就存储在0-5空间上
flip():接下来我们需要把写入的数据读取出来,这也是buffer的使用场景,那么我们需要调用flip()进行位置翻转
buffer.flip();
执行flip()之后参数变化:
通过上图我们发现 position和limit发生了变化,postion变为:0,limit变为:6(这是flip()翻转之前的postion值)。那么此时我们就可以读取buffer中的数据了
while(buffer.hasRemaining()){
System.out.println((char) buffer.get());
}
下面是buffer.hasRemaining()的代码
通过下面 hasRemaining()的源码我们可以看出,我们只能get()出0-5的位置上的数据,调用while()循环我们会依次打印出1、2、3、4、5、6
public final boolean hasRemaining() {
return position < limit;
}
接下来我们说下mark()和reset()如何配合使用。
举例一个使用场景我们能更好的理解,假设在读取读取4、5的时候我们需要做一些事务计算,比如g(f(4),f(5)),只要计算错误我们就需要重新读取计算,那么这时候我们就会用到mark()和reset()。
先贴出代码
while(buffer.hasRemaining()){
char c=(char)buffer.get();
System.out.println(c);
if(buffer.position()==3){
buffer.mark();
}
if(buffer.position()==4){
a=f(c);
}
if(buffer.position()==5){
b=f(c);
try {
System.out.println(g(a,b));
throw new Exception("主动抛出");
} catch (Exception e) {
buffer.reset();
}
}
}
在postion=3时,执行mark()后,mark=3;抛出异常,catch里执行reset()后,postion=mark=3,重新读取4、5。dubug的视图就不再贴出来了。
通过上面论述,相信大家对ByteBuffer的重要参数已经有系统的了解,接下来rewind()和clear()就不难理解了。
以下是这两个方法的源码
rewind:重置mark并将potion设置到起始位置0
clear:重置ByteBuffer的重要参数
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}