Buffer的capacity,position和limit
为了理解Buffer的工作原理,需要熟悉它的三个属性:
- capacity
- position
- limit
position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。
capacity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
position
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer 后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前 写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
问题 ?为什么打印的是0
ByteBuffer bu = ByteBuffer.allocate(10);
bu.put((byte)'A');
bu.put((byte)'2');
bu.put((byte)'3');
bu.put((byte)'4');
bu.put((byte)'5');
System.out.println(bu.get());
首先,当前的缓冲是处于写的模式,当执行到 bu.put((byte)'5'); 这段代码的时候。 position的值应该为5(下一个可插入数据的单元,),当前位置是null。
所以,在调用get()的时候。当前position是没有值的。所以会是0,当我们调用 bu.blip(); 在打印的就是65了。打开bpli源码可发现
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }
其实他就是把上次的position值,赋给了limit(读的时候的上界)。并且把position初始化为0.所以get的时候会打印65(是A的Unicode码)了
rewind()方法 (仅仅是重新读取,不会对内存的数据造成影响)
Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)。
clear()与compact()方法
一旦读完Buffer中的数据,需要让Buffer准备好再次被写入。可以通过clear()或compact()方法来完成。
如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。
如果Buffer中有一些未读的数据,调用clear()方法,数据将“被遗忘”,意味着不再有任何标记会告诉你哪些数据被读过,哪些还没有。
如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。
compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。