buffer java nio_JavaNIO中Buffer的基本概念

Buffer是Java NIO中最基本的概念,也是java.nio包中的最基础的类。《Java NIO》书中对Buffer的描述是“a holding tank, or staging area”,而在《Thinking in Java》则把Buffer比作穿梭于矿井和外部之间的,运载矿物的货车。实际上,在Java NIO中的设计更为接近操作系统底层的实际运作,运用Buffer也是为了提高IO效率,这篇我们就来看下Buffer相关的最基本的内容。

0.  Buffer

Buffer是Java

API在java.nio包中的第一个类,而java.nio包中的类大部分都是Buffer的子类。Buffer类本身是抽象的,甚至连put()、

get()方法都没有给出,它主要有这样一些直接子类,分别和非布尔的基本类型对应: ByteBuffer, CharBuffer,

DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer。

再来看JDK中Buffer类的实现,是围绕对应于Buffer的一个数组展开的,Buffer类中给出了如下4个属性变量:

mark 在某些条件下,需要特殊标记position位置时会用到

position  指向当前位置的数组index

limit 指向可以访问的结尾的数组index,默认等同于capacity

capacity 指向数组最大位置的index(+1)

另外,这4个属性变量中前后每两个都恒有<=关系。

和这4个属性对应,Buffer中还提供了一些相关的方法:

mark() 标记mark位当前position位置

reset() 恢复position到mark位置,前提是mark不为默认值-1

position()和position(int) 前者获取当前position值,后者设置position值

clear() 恢复到最初的状态,即mark为-1,position为0,limit为capacity,为新一轮channel的读操作做准备

flip() 为新一轮写操作做准备,和clear()不同的地方是把limit设置为position,而非capacity

rewind() 和flip()类似,不同之处在于不会设置limit到position位置

有意思的是,上述方法大部分都是返回Buffer类型的,即Buffer对象本身,可以用来连续做实例方法调用。

此外,Buffer中有array()和arrayOffset()方法,但是是抽象的未实现的方法。

还有address属性,按注释说明,是Direct Buffer才会用到。

1. CharBuffer等其他基本类型对应的Buffer子类

关于Buffer的子类,我们可以看如下图。

49581389_1.png

Buffer的子类

我们看到这些直接子类都有A标记,也就是说它们都是抽象类。

这些类的具体实现都是Java API之外的,往往都和具体的平台底层结构有关,它们封装了如字节序处理相关等内容。但对于上述这些Buffer子类,我们通常不必关心其具体实现。我们只需要通过allocate()和wrap()方法来分配或者初始化即可。

allocate()和wrap()都是静态方法,在Buffer的子类中有实现。其中allocate()是新分配,而wrap()则可以通过实

现实例化的数组作为Buffer的数据存储支持。其中ByteBuffer还有allocateDirect()方法,这个后面的文章详细说明。

对应地,子类也都给出了Buffer类中array()和arrayOffset()的具体实现,在Buffer使用堆中的数组支持的并且非只读情况下,会分别返回数组和偏移量。有hasArray()方法判断前两者的可用性。

还有,最基本地,这些Buffer的直接子类也都给出了各种重载的put()和get()方法,但是是抽象的,具体实现在这些Buffer直接子类的具体子类中实现。如用堆中数组作为数据支持的实现中,put()和get()则分别是对数组进行存取操作。

除了上面所说的,这些子类也基本都提供了这样几个方法:

compact() 这个方法也与Buffer标记相关的四个基本属性变量有关,通常是在读了一部分数据之后又开始写数据,把未读的数据拷贝至开头段,并设置各指针准备继续写入。

compareTo() 这个方法则与具体的类型有关,Buffer的几个子类基本都是先了Comparable接口。

duplicate() 复制,生成一个新的Buffer子类对象,在Buffer个子类中是抽象的;通常在堆实现的情况下,使用的仍是同一个支持数据存储的数组。

slice() 和上一个类似,只是角标有所调整。

其它的就是个子类结合类型的情况和实现不同的接口提供的方法了,如CharBuffer实现了Appendable接口,有append()方法等。

2. 其它

上面已经对Buffer和Buffer各子类通用的最基本的内容做了阐述。而在JDK实现上不同平台有所不同,这个就不做细节介绍了,可以参见对应平台的JDK源码。

而ByteBuffer是直接对应字节处理的,比较特殊。关于ByteBuffer的特征,后文会详细整理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值