标签:ntb within param rect byte 缓冲 rem bool als
简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer、ByteBuffer、DoubleBuffer等的源码),Buffer类内部其实就是一个基本数据类型的数组,以及对这个缓冲数组的各种操作;
常见的缓冲区如ByteBuffer、IntBuffer、DoubleBuffer...内部对应的数组依次是byte、int、double...
在Java NIO中,缓冲区主要是跟通道(Channel)打交道,数据总是从缓冲区写入到通道中,或者从通道读取数据到缓冲区;
关于Buffer的继承结构,我们可以简单的以ByteBuffer为例,如下:
Buffer是顶层抽象类,ByteBuffer继承Buffer,也是抽象类,ByteBuffer最常见的两个具体实现类如下:
DirectByteBuffer(JVM堆外部、通过unsafe.allocateMemory实现)、HeapByteBuffer(JVM堆)
capacity指的是缓冲区能够容纳元素的最大数量,这个值在缓冲区创建时被设定,而且不能够改变,如下,我们创建了一个最大容量为10的字节缓冲区;
ByteBuffer bf = ByteBuffer.allocate(10);
limit指的是缓冲区中第一个不能读写的元素的数组下标索引,也可以认为是缓冲区中实际元素的数量;
position指的是下一个要被读写的元素的数组下标索引,该值会随get()和put()的调用自动更新;
一个备忘位置,调用mark()方法的话,mark值将存储当前position的值,等下次调用reset()方法时,会设定position的值为之前的标记值;
根据以上四个属性的定义,我们可以总结出它们之间的关系如下:
0 <= mark <= position <= limit <= capacity
1、创建一个容量大小为10的字符缓冲区
ByteBuffer bf = ByteBuffer.allocate(10);
此时:mark = -1; position = 0; limit = 10; capacity = 10;
2、往缓冲区中put()五个字节
bf.put((byte)‘H‘).put((byte)‘e‘).put((byte)‘l‘).put((byte)‘l‘).put((byte)‘0‘);
注意这里一个字符是占用两个字节的,但是英文字符只占用一个字节,所以这样是可以实现储存效果的;
此时:mark = -1; position = 5; limit = 10; capacity = 10;
3、调用flip()方法,切换为读就绪状态
bf.flip();
此时:mark = -1; position = 0; limit = 5; capacity = 10;
4、读取两个元素
System.out.println("" + (char) bf.get() + (char) bf.get());
此时:mark = -1; position = 2; limit = 5; capacity = 10;
5、标记此时的position位置
bf.mark();
此时:mark = 2; position = 2; limit = 5; capacity = 10;
6、读取两个元素后,恢复到之前mark的位置处
System.out.println("" + (char) bf.get() + (char) bf.get()); bf.reset();
属性变化情况:
执行完第一行代码:mark = 2; position = 4; limit = 5; capacity = 10;
执行完第二行代码:mark = 2; position = 2; limit = 5; capacity = 10;
7、调用compact()方法,释放已读数据的空间,准备重新填充缓存区
bf.compact();
此时:mark = 2; position = 3; limit = 10; capacity = 10;
注意观察数组中元素的变化,实际上进行了数组拷贝,抛弃了已读字节元素,保留了未读字节元素;
其实查看equals源码就可以知道是如何比较的,如下(以ByteBuffer为例):
public boolean equals(Object ob) { if (this == ob) return true; if (!(ob instanceof ByteBuffer)) return false; ByteBuffer that = (ByteBuffer)ob; if (this.remaining() != that.remaining()) return false; int p = this.position(); for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) if (!equals(this.get(i), that.get(j))) return false; return true; }
总的来说,两个缓冲区被认为相等的条件如下(以下内容直接摘自《Java NIO》):
以ByteBuffer为例,使用如下API即可:
public ByteBuffer get(byte[] dst, int offset, int length)
public ByteBuffer put(byte[] src, int offset, int length)
public ByteBuffer get(byte[] dst)
public final ByteBuffer put(byte[] src)
实际上,后面两种方法内部就是调用前面两种方法的;
参数的含义直接查看源码注释即可,写的很清楚,如put(byte[] src, int offset, int length)方法的注释:
/* @param src * The array from which bytes are to be read * * @param offset * The offset within the array of the first byte to be read; * must be non-negative and no larger than <tt>array.length</tt> * * @param length * The number of bytes to be read from the given array; * must be non-negative and no larger than * <tt>array.length - offset</tt> */
《Java NIO》
标签:ntb within param rect byte 缓冲 rem bool als
原文地址:http://www.cnblogs.com/chenpi/p/6475510.html