javaNIO中涉及缓存的类有很多,除了boolean类型外,每种基本类型都有对应的缓冲区类,包括CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer和ShortBuffer。
所有的缓存区都有以下属性:
- 容量(capacity):表示该缓存区可以保存多少数据。
- 极限(limit):表示缓存区的当前终点,是逻辑终点,物理终点应该是capacity,不能对缓冲区中超过极限的区域进行写操作。极限值是可以修改的,所以可以更加灵活操作缓存区。
- 位置(position):表示缓存区中下一个读写单元的位置,每次读写缓冲区的数据时,都会改变该值,为下一次读写数据做准备。
以上提到的缓冲区类都是能够返回自身实例的静态工厂方法allocate(intcapacity)。本次通过分析ByteBuffer源码,分析缓存工作过程。与ByteBuffer有关的还有两个类:HeapByteBuffer和Buffer。Buffer是ByteBuffer的父抽象类,定义了mark,position,limit,capacity四个属性。ByteBuffer是针对Byte类型的缓存类,定义了hb属性,类型为byte[]。HeapByteBuffer是ByteBuffer的实现类。
ByteBuffer初始化过程:
1:allocate分配函数中返回的是ByteBuffer的子类HeapByteBuffer的对象。
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>{
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
}
2:HeapByteBuffer构造函数如下:cap=capacity;lim=capacity;仍然是调用父类,也就是ByteBuffer的构造函数。
class HeapByteBuffer extends ByteBuffer
{
HeapByteBuffer(int cap, int lim) {
super(-1, 0, lim, cap, new byte[cap], 0);
}
}
3:ByteBuffer构造函数如下:mark=-1;pos=0;lim=lim=capacity;cap=cap=capacity;hb=new byte[cap],offset=0;,ByteBuffer仍然调用父类,也就是Buffer的构造函数后,初始化hb和offset。
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>
{
ByteBuffer(int mark, int pos, int lim, int cap,byte[] hb, int offset){
super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}
}
4:Buffer构造函数如下:mark=-1;lim=lim=lim=capacity;pos=0;cap=cap=cap=capacity
Buffer(int mark, int pos, int lim, int cap) {
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap; //初始化capacity
limit(lim); //检查lim
position(pos); //检查position
if (mark >= 0) { //检查mark
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("+ mark + " > " + pos + ")");
this.mark = mark;
}
}
5:limit检查函数
public final Buffer limit(int newLimit) {
if ((newLimit > capacity) || (newLimit < 0)) //limit不能设置大于capacity或者小于0
throw new IllegalArgumentException();
limit = newLimit; //初始化limit属性
if (position > limit) position = limit; //如果当前position大于limit,position=limit
if (mark > limit) mark = -1; //如果mark大于limit,mark=-1
return this;
}
6:position检查函数
public final Buffer position(int newPosition) {
if ((newPosition > limit) || (newPosition < 0)) //position不能设置大于limit或者小于0
throw new IllegalArgumentException();
position = newPosition; //初始化position
if (mark > position) mark = -1; //如果mark>position,mark=-1
return this;
}
初始化完成后,HeapByteBuffer存储过程源码如下:
存过程:
public ByteBuffer put(byte x) {
hb[ix(nextPutIndex())] = x;
return this;
}
public ByteBuffer put(int i, byte x) {
hb[ix(checkIndex(i))] = x;
return this;
}
final int nextPutIndex() {
if (position >= limit)//如果当前位置值或等于限制值,则表示没有空间能使用
throw new BufferOverflowException();
return position++; //否则返回当前空的一位空间
}
final int nextPutIndex(int nb) {
if (limit - position < nb) //想要存储的位置只能在当前位置值和限制值中间,否则报错
throw new BufferOverflowException();
int p = position;
position += nb; //返回要存储的位置
return p;
}
protected int ix(int i) {
return i + offset; //i+偏移位
}
取过程如下,与存过程类似:
public byte get() {
return hb[ix(nextGetIndex())];
}
public byte get(int i) {
return hb[ix(checkIndex(i))];
}
final int nextGetIndex() {
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
final int nextGetIndex(int nb) {
if (limit - position < nb)
throw new BufferUnderflowException();
int p = position;
position += nb;
return p;
}
缓存函数:
1.Buffer抽象类下的clear()
public final Buffer clear() {
position = 0; //位置设置为0
limit = capacity; //限制设置为当前容量值
mark = -1; //mark为-1
return this;
}
2.Buffer抽象类下的flip()
public final Buffer flip() {
limit = position; //限制设置为当前位置
position = 0; //当前位置设置为0
mark = -1; //mark=-1
return this;
}
3.Buffer抽象类下的rewind()
public final Buffer rewind() {
position = 0; //当前位置为0
mark = -1; //mark为-1
return this;
}