Java NIO 缓冲区Buffer(一)基础学习
Buffer本质:
是一块可以写入数据,然后可以从中读取数据的内存区域。这块内存被包装成NIO Buffer对象。由此提供了一些列API用于操作这块内存区域。
交互:
主要是和通道(Channel)进行数据交互。数据从通道读入缓冲区,从缓冲区写入通道。
基本属性:
1 // Invariants: mark <= position <= limit <= capacity 2 private int mark = -1; 3 private int position = 0; 4 private int limit; 5 private int capacity;
capacity(容量):
缓冲区能够容纳的数据元素的最大数量。这一容量在创建时被设定,永远不能改变。
limit(上界):
缓冲区的第一个不能读或者写的数据。或者说是缓冲区中现存的元素的计数。
position(位置):
下一个要被读或者写的元素的索引。位置会自动由get()或者put()函数更新。
mark(标记):
备忘位置。通过mark()来设定mark=position。调用reset()来设定position=mark。
实例观察和感悟:
1. 初始化一个Buffer
ByteBuffer bf = ByteBuffer.allocate(10);
2.添加几个数据,Buffer支持级联调用
bf.put((byte)'H').put((byte)'E').put((byte)'L').put((byte)'L').put((byte)'O');
3.切换状态,从写模式切换到读模式
bf.flip();
4.尝试读一读里面的数据。读取两次,可以看见position位置改变了。
1 bf.get(); 2 bf.get();
5.标记一下当前读到哪个位置。标记的返回值是Buffer对象。
bf.mark();
6.再读取两次数据。
bf.get();
bf.get();
7.恢复操作,reset
8. compact方法,释放已读数据,重新填充缓存区。
bf.compact();
9. equals,重写了Object内的equals方法。
1 public boolean equals(Object ob) { 2 if (this == ob) 3 return true; 4 if (!(ob instanceof ByteBuffer)) 5 return false; 6 ByteBuffer that = (ByteBuffer)ob; 7 if (this.remaining() != that.remaining()) 8 return false; 9 int p = this.position(); 10 for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) 11 if (!equals(this.get(i), that.get(j))) 12 return false; 13 return true; 14 }
1. 如果比较的就是当前Buffer,肯定相等。
2. 如果不是ByteBuffer对象,肯定不想等(此处是拿ByteBuffer源码分析)。
3. 剩余元素需要保持相等,两个对象才相等,这就意味着Buffer的容量不需要保持相同,只看剩余元素数量。
4. position位置开始直到limit位置的值必须相等,两个对象才相等。(被Get()函数返回的剩余元素序列必须一致)。
其实Buffer对象的相等还是比较好理解的,简单的说就是看position位置和limit位置中间的值是否相等,并且剩余元素数量是否相等就可以了。
图2中不相等对象看起来大家数据都一样,但是位置不一样,导致get()出来的数据不一样,所以不满足比较要求。