0%

Java NIO Buffer解析

主要属性

  • capacity
    作为一个内存块,Buffer有一个固定的大小值,也叫capacity.你只能往里写capacity个byte、long、char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。

  • position
    当你写数据到Buffer中时,position表示当前的位置。初始的position值为0。position最大可为capacity–1。当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。

  • limit
    在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。写模式下,limit等于Buffer的capacity。当切换Buffer到读模式时,limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据。

  • 三者关系如下:

Buffer构造器

尽管Buffer是一个抽象类,但是依然有自己的构造器。
其主要作用是初始化抽象类的成员和子类的初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
Buffer(int mark, int pos, int lim, int cap) {       // package-private
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;
}
}

Buffer常用方法

  • allocate() 分配一段空间的Buffer对象
  • put() 用于往Buffer中添加元素
  • flip() 用于将写模式转化为读模式
  • hasRemaining() 判断Buffer中是否还有元素可读
  • get() 读取Buffer中position位置的元素
  • clear() 清空Buffer
  • compact() 清除已读取的部分

关于Buffer的数据结构

通过查看java.nio.IntBuffer这个类的初始化函数及成员(如下),可以确定,Buffer的基本数据结构是数组!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final int[] hb;                  // Non-null only for heap buffers
final int offset;
boolean isReadOnly; // Valid only for heap buffers

// Creates a new buffer with the given mark, position, limit, capacity,
// backing array, and array offset
//
IntBuffer(int mark, int pos, int lim, int cap, // package-private
int[] hb, int offset)
{
super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}

关于compact函数的实现

这个函数我是比较感兴趣的,他与clear()的区别是只删除已读的部分。

通过查看java.nio.HeapIntBuffer,该类是java.nio.IntBuffer的子类,可以得知compact函数的实现。

1
2
3
4
5
6
7
8
9
10
11
public IntBuffer compact() {
// 将剩余的没有访问的元素拷贝到Buffer从零开始的位置
System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
// 重置position
position(remaining());
// 重置limit
limit(capacity());
// 删除mark
discardMark();
return this;
}

参考文献

  1. Java NIO
  2. Java NIO 系列教程
  3. Java源码