ByteBuffer源码解读

  javaNIO中涉及缓存的类有很多,除了boolean类型外,每种基本类型都有对应的缓冲区类,包括CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer和ShortBuffer。

  所有的缓存区都有以下属性:

  • 容量(capacity):表示该缓存区可以保存多少数据。
  • 极限(limit):表示缓存区的当前终点,是逻辑终点,物理终点应该是capacity,不能对缓冲区中超过极限的区域进行写操作。极限值是可以修改的,所以可以更加灵活操作缓存区。
  • 位置(position):表示缓存区中下一个读写单元的位置,每次读写缓冲区的数据时,都会改变该值,为下一次读写数据做准备。

  以上提到的缓冲区类都是能够返回自身实例的静态工厂方法allocate(intcapacity)。本次通过分析ByteBuffer源码,分析缓存工作过程。与ByteBuffer有关的还有两个类:HeapByteBuffer和Buffer。Buffer是ByteBuffer的父抽象类,定义了mark,position,limit,capacity四个属性。ByteBuffer是针对Byte类型的缓存类,定义了hb属性,类型为byte[]。HeapByteBuffer是ByteBuffer的实现类。

  ByteBuffer初始化过程:

  1:allocate分配函数中返回的是ByteBuffer的子类HeapByteBuffer的对象。

  public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>{
    public static ByteBuffer allocate(int capacity) {
    if (capacity < 0)
      throw new IllegalArgumentException();
     return new HeapByteBuffer(capacity, capacity);
   }
  }

  2:HeapByteBuffer构造函数如下:cap=capacity;lim=capacity;仍然是调用父类,也就是ByteBuffer的构造函数。

  class HeapByteBuffer extends ByteBuffer
  {  
     HeapByteBuffer(int cap, int lim) {           
          super(-1, 0, lim, cap, new byte[cap], 0);
      }
  }

  3:ByteBuffer构造函数如下:mark=-1;pos=0;lim=lim=capacity;cap=cap=capacity;hb=new byte[cap],offset=0;,ByteBuffer仍然调用父类,也就是Buffer的构造函数后,初始化hb和offset。

  public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>
  {
      ByteBuffer(int mark, int pos, int lim, int cap,byte[] hb, int offset){
          super(mark, pos, lim, cap);
          this.hb = hb;
          this.offset = offset;
      }
  }

  4:Buffer构造函数如下:mark=-1;lim=lim=lim=capacity;pos=0;cap=cap=cap=capacity

  Buffer(int mark, int pos, int lim, int cap) {     
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        this.capacity = cap;  //初始化capacity
        limit(lim);       //检查lim
        position(pos);     //检查position
        if (mark >= 0) {    //检查mark
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("+ mark + " > " + pos + ")");
            this.mark = mark;
        }
    }

  5:limit检查函数

  public final Buffer limit(int newLimit) {
        if ((newLimit > capacity) || (newLimit < 0))  //limit不能设置大于capacity或者小于0
            throw new IllegalArgumentException();
        limit = newLimit;                  //初始化limit属性
        if (position > limit) position = limit;      //如果当前position大于limit,position=limit
        if (mark > limit) mark = -1;            //如果mark大于limit,mark=-1
        return this;
    }

  6:position检查函数

   public final Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))  //position不能设置大于limit或者小于0
            throw new IllegalArgumentException();
        position = newPosition;                //初始化position
        if (mark > position) mark = -1;           //如果mark>position,mark=-1
        return this;
    }

  初始化完成后,HeapByteBuffer存储过程源码如下:

  存过程:

  public ByteBuffer put(byte x) {
        hb[ix(nextPutIndex())] = x;
        return this;
    }

    public ByteBuffer put(int i, byte x) {
        hb[ix(checkIndex(i))] = x;
        return this;
    }
  final int nextPutIndex() {                     
  if (position >= limit)//如果当前位置值或等于限制值,则表示没有空间能使用
   throw new BufferOverflowException();
  return position++;  //否则返回当前空的一位空间
  }

  final int nextPutIndex(int nb) {
   if (limit - position < nb)  //想要存储的位置只能在当前位置值和限制值中间,否则报错
   throw new BufferOverflowException();
  int p = position;    
   position += nb;        //返回要存储的位置
   return p;
  }
  protected int ix(int i) {
   return i + offset;  //i+偏移位
  }

  取过程如下,与存过程类似:

  public byte get() {
      return hb[ix(nextGetIndex())];
  }

  public byte get(int i) {
      return hb[ix(checkIndex(i))];
  }
  final int nextGetIndex() {                          
   if (position >= limit)
   throw new BufferUnderflowException();
   return position++;
  }

  final int nextGetIndex(int nb) {
   if (limit - position < nb)
   throw new BufferUnderflowException();
   int p = position;
   position += nb;
   return p;
  }

  缓存函数:

  1.Buffer抽象类下的clear()

  public final Buffer clear() {
        position = 0;    //位置设置为0
        limit = capacity;  //限制设置为当前容量值
        mark = -1;      //mark为-1
        return this;
    }

  2.Buffer抽象类下的flip()

  public final Buffer flip() {
        limit = position;  //限制设置为当前位置
        position = 0;    //当前位置设置为0
        mark = -1;      //mark=-1
        return this;
    }

  3.Buffer抽象类下的rewind()

  public final Buffer rewind() {
        position = 0;    //当前位置为0
        mark = -1;      //mark为-1
        return this;
    }

  

posted @ 2018-01-10 10:40  浩天817  阅读(424)  评论(0编辑  收藏  举报