所属包
package java.nio;
继承与实现关系
public abstract class Buffer
Buffer缓冲区原理图
20180130141414174.png常用的变量
//临时备忘位置变量
private int mark = -1;
/**
* 在写模式下,position从0开始写,一直可以写到capacity-1。
* 在读模式下,position从某个位置去读,如果从写切换到读,那么position被设置为0。
*/
private int position = 0;
/**
* 缓冲区可读可写的容量,可读可写limit最大情况下,limit=capacity
*/
private int limit;
/**
* 缓冲区的总容量
*/
private int capacity;
//指向缓冲区的地址
long address;
构造器
//创建一个指定mark、pos、limit、capacity参数的构造器
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;
}
}
方法
limit方法:设置缓冲区的限制。
/**
* 设置缓冲区的限制。
* 如果position>limit,那么重新设置新的limit。
* 如果mark>limit,那么最新的limit将会被抛弃。
*/
public final Buffer limit(int newLimit) {
//如果输入参数newLimit大于缓冲区最大容量capacity或者小于0,那么抛出非法参数异常。
if ((newLimit > capacity) || (newLimit < 0))
throw new IllegalArgumentException();
//设置输入参数newLimit为缓冲区最新的limit。
limit = newLimit;
//如果开始读写的位置大于了已存放数据的容量,那么将读写位置设置为已存放数据的容量。
if (position > limit) position = limit;
//如果临时备忘位置大于已存放数据的容量,那么将mark设置为-1。
if (mark > limit) mark = -1;
//返回当前的缓冲区Buffer
return this;
}
position方法:设置读写的开始位置。
/**
* 设置读写的开始位置。
* 如果mark>position,那么position这个变量将会被抛弃。
*/
public final Buffer position(int newPosition) {
//如果输入参数newPosition大于可读可写的最大容量或者newPosition小于0,那么抛出非法参数异常。
if ((newPosition > limit) || (newPosition < 0))
throw new IllegalArgumentException();
//设置输入参数newPosition作为最新的读写开始位置。
position = newPosition;
//如果临时备忘位置mark大于position,设置mark为-1。
if (mark > position) mark = -1;
//返回当前的缓冲区Buffer
return this;
}
/**
* 获取当前缓冲区Buffer的最大容量
*/
public final int capacity() {
return capacity;
}
/**
* 获取当前缓冲区Buffer的读写开始位置
*/
public final int position() {
return position;
}
/**
* 获取当前缓冲区Buffer的读写的最大容量
*/
public final int limit() {
return limit;
}
/**
* 设置当前缓冲区的备忘变量为position
* 返回当前最新缓冲区Buffer
*/
public final Buffer mark() {
mark = position;
return this;
}
/**
* 将缓冲区Buffer的位置position设置为以前临时备忘变量mark存储的位置。
*/
public final Buffer reset() {
//获取当前临时备忘变量mark
int m = mark;
//如果临时备忘变量m小于0,那么抛出无效的标记异常。
if (m < 0)
throw new InvalidMarkException();
//设置当前缓冲区读写开始位置为备忘变量mark
position = m;
//返回当前最新缓冲区Buffer
return this;
}
/**
* 清除缓冲区
*/
public final Buffer clear() {
//设置读写开始位置position为0
position = 0;
//设置读写的最大容量limit为缓冲区最大容量capacity
limit = capacity;
//设置临时备忘变量值为-1
mark = -1;
//返回当前最新缓冲区Buffer
return this;
}
/**
* 反转此缓冲区
* 在进行写完去读的时候使用
*/
public final Buffer flip() {
//将读写的最大容量设置为当前的位置
limit = position;
//将position设置为0
position = 0;
//设置临时备忘变量为-1
mark = -1;
//返回当前最新的缓冲区Buffer
return this;
}
/**
* 重绕此缓冲区
* 在通道写入或者获取之前调用
*/
public final Buffer rewind() {
//设置当前位置为0
position = 0;
//将临时备忘变量设置为-1
mark = -1;
//返回当前最新的缓冲区Buffer
return this;
}
/**
* 返回当前的缓冲区Buffer的剩余元素的数量
*/
public final int remaining() {
return limit - position;
}
/**
* 返回当前的缓冲区中是否有元素
* 如果有就返回true
* 如果没有就返回false
*/
public final boolean hasRemaining() {
return position < limit;
}
/**
* 当前的缓冲区是否只读
* 如果是就返回true
* 如果不是就返回false
*/
public abstract boolean isReadOnly();
/**
* 当前的缓冲区是否可以访问底层的数组
*/
public abstract boolean hasArray();
/**
* 返回当前缓冲区的底层实现数组
*/
public abstract Object array();
/**
* 返回此缓冲区的底层实现数组中第一个缓冲区元素的偏移量(可选操作)。
*/
public abstract int arrayOffset();
/**
* 此缓冲区是否为直接缓冲区
*/
public abstract boolean isDirect();
// -- Package-private methods for bounds checking, etc. --
/**
* 获取当前位置的下一个位置
*/
final int nextGetIndex() {
//如果当前位置大于等于limit,抛出缓冲区向下溢出异常。
if (position >= limit)
throw new BufferUnderflowException();
//返回当前位置的下一个位置
return position++;
}
/**
* 当前位置增加指定参数的长度
* 返回未增加前的位置
*/
final int nextGetIndex(int nb) {
//如果limit值减去当前位置值小于nb,抛出缓冲区向下溢出异常。
if (limit - position < nb)
throw new BufferUnderflowException();
int p = position;
position += nb;
return p;
}
/**
* 自增当前位置
*/
final int nextPutIndex() { // package-private
if (position >= limit)
throw new BufferOverflowException();
return position++;
}
/**
* 当前位置增加指定参数的长度
* 返回增加之前的位置
*/
final int nextPutIndex(int nb) { // package-private
if (limit - position < nb)
throw new BufferOverflowException();
int p = position;
position += nb;
return p;
}
/**
* 检查参数i是否小于limit
*/
final int checkIndex(int i) { // package-private
if ((i < 0) || (i >= limit))
throw new IndexOutOfBoundsException();
return i;
}
/**
* 检查参数i是否小于limit-指定的参数
*/
final int checkIndex(int i, int nb) { // package-private
if ((i < 0) || (nb > limit - i))
throw new IndexOutOfBoundsException();
return i;
}
//返回临时备忘变量值
final int markValue() { // package-private
return mark;
}
//清空缓冲区的容量
final void truncate() { // package-private
mark = -1;
position = 0;
limit = 0;
capacity = 0;
}
//抛弃临时备忘变量
final void discardMark() { // package-private
mark = -1;
}
阅读总结
①在写完去读的时候,使用flip方法,特点就是将读的容量limit设置为写的position,将读的开始位置position设置为0,将mark设置为-1(至于为什么,可以参考前面的原理图进行思考)。
②在读完去写的时候,使用clear方法,特点就是将position设置为0,写的limit值设置为当前缓冲区的capacity,将mark设置为-1。
③至于mark和reset方法,它们的作用就是将position恢复到原位。
---------------------------该源码为jdk1.7版本的
网友评论