参考书籍:Java NIO
IO系列的学习主要是为了增强自己在IO方面的不足,前面很多系列的学习都没有涉及到IO部分,因此打算从NIO开始,逐步去学习IO相关的知识。
本质:
是一块可以写入数据,然后可以从中读取数据的内存区域。这块内存被包装成NIO Buffer对象。由此提供了一些列API用于操作这块内存区域。
交互:
主要是和通道(Channel)进行数据交互。数据从通道读入缓冲区,从缓冲区写入通道。
基本属性:
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0;
private int limit;
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位置改变了。
bf.get();
bf.get();

5.标记一下当前读到哪个位置。标记的返回值是Buffer对象。
bf.mark();

6.再读取两次数据。
bf.get();
bf.get();

7.恢复操作,reset
8. compact方法,释放已读数据,重新填充缓存区。
bf.compact();

9. equals,重写了Object内的equals方法。
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;
}
1. 如果比较的就是当前Buffer,肯定相等。
2. 如果不是ByteBuffer对象,肯定不想等(此处是拿ByteBuffer源码分析)。
3. 剩余元素需要保持相等,两个对象才相等,这就意味着Buffer的容量不需要保持相同,只看剩余元素数量。
4. position位置开始直到limit位置的值必须相等,两个对象才相等。(被Get()函数返回的剩余元素序列必须一致)。
其实Buffer对象的相等还是比较好理解的,简单的说就是看position位置和limit位置中间的值是否相等,并且剩余元素数量是否相等就可以了。
图2中不相等对象看起来大家数据都一样,但是位置不一样,导致get()出来的数据不一样,所以不满足比较要求。
NIO的学习应该说现阶段都是在读书,因此这些都只能当做一个读后感和关键点记录的文章,没有自己的使用心得,但愿自己后续能使用到NIO,然后来补充自己的体验吧。