admin管理员组

文章数量:1611915

概述


  • postion
  • capacity
  • limit

这三个属性是Buffer对象的关键属性,要理解NIO中的Buffer,必须先理解这三个属性,本文会使用一些简单例子来逐步说明三个属性的含义。

下文的所有demo都是使用IntBuffer来做演示的

理解capacity


 public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        System.out.println("capacity:"+intBuffer.capacity());
 }

当创建一个固定容量的IntBuffer后,capacity的内容如下

capacity:5

Buffer对象是一个容器(底层用数组实现),里面可以存储JAVA基本类型数据,像int、byte、long等。
其中Buffer对象的capacity属性表示容器的容量,这个是不能变的。通过

IntBuffer.allocate(5)

创建一个capacity=5的IntBuffer对象,这个IntBuffer对象只能存储5个数字。

public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(0);
        System.out.println("capacity:"+intBuffer.capacity());

        intBuffer.put(1);
        intBuffer.put(2);
        intBuffer.put(3);
        intBuffer.put(4);
        intBuffer.put(5);
        intBuffer.put(6);
}

如果试图为IntBuffer添加第6个数字,将会抛出

java.nio.BufferOverflowException


理解position


概念

下一个要被读或写的元素的位置,当调用相应的get( )和put( )方法,postion会被修改。

public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        System.out.println("position:"+intBuffer.position());
}

当刚创建一个Buffer对象时,还未进行put和get操作,postion的初始值为0。
执行上面的代码,输出如下

position:0

当往Buffer对象中put元素的时候,postion随着移动。

public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        intBuffer.put(1);
        intBuffer.put(2);
        System.out.println("position:"+intBuffer.position());
}

运行代码,执行结果如下

position:2

这里的2表示,put下一个元素的时候,可以在2这个位置上插入数据。要移动Buffer对象中postion的位置,
另外一个办法是使用get()方法,每调用一次,postion增加1。

 public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        intBuffer.put(1);
        intBuffer.put(2);
        System.out.println("position:"+intBuffer.position());
        System.out.println("=======================");

        System.out.println(intBuffer.get());
        System.out.println("position:"+intBuffer.position());
        System.out.println("=======================");

        System.out.println(intBuffer.get());
        System.out.println("position:"+intBuffer.position());
        System.out.println("=======================");

        System.out.println(intBuffer.get());
        System.out.println("position:"+intBuffer.position());
        System.out.println("=======================");
}

上面的代码输出如下

position:2
=======================
0
position:3
=======================
0
position:4
=======================
0
position:5
=======================

总共调用了3次get方法,但是3次get方法的返回值都是0。当多调用一次get()方法的时候,将会抛出

java.nio.BufferUnderflowException

原因是positon已经超过capacity了。

那么如何获取Buffer对象中的元素呢?可以使用get(index)方法,读取元素的时候,指定索引。
备注

get(index)方法是不会改变postion位置的。

 public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        intBuffer.put(1);
        intBuffer.put(2);

        System.out.println(intBuffer.get(0));
        System.out.println("postion:"+intBuffer.position());
        System.out.println("================");
        System.out.println(intBuffer.get(1));
        System.out.println("postion:"+intBuffer.position());
}

输出结果如下

1
postion:2
================
2
postion:2

如果想替换某个index上的值,可以使用

put(int index, int i)

 public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        intBuffer.put(1);
        intBuffer.put(2);

        System.out.println(intBuffer.get(0));
        System.out.println("postion:"+intBuffer.position());
        System.out.println("================");
        System.out.println(intBuffer.get(1));
        System.out.println("postion:"+intBuffer.position());

        System.out.println("================");
        intBuffer.put(0,3);
        System.out.println(intBuffer.get(0));
}

执行结果如下

1
postion:2
================
2
postion:2
================
3

0这个index上的值已经从1改成3了。


理解limit


得从两个角度来理解limit。

  • 当往Buffer对象里put数据的时候,limit一直都是等于capacity,表示最多能往Buffer对象里写多少数据
  • 当调用Buffer对象的flip()方法后,想从Buffer对象读取数据时,position被设置为0,limit被设置为之前的postion,这个时候的limit表示最多能从Buffer读取多少数据。换句话说,你能读到之前写入的所有数据。
 public static void main(String[] args){
        IntBuffer intBuffer = IntBuffer.allocate(5);
        intBuffer.put(1);
        intBuffer.put(2);
        System.out.println("limit:"+intBuffer.limit());
        System.out.println("postion:"+intBuffer.position());

        intBuffer.flip();
        System.out.println("调用flip方法后");
        System.out.println("postion:"+intBuffer.position());
        System.out.println("limit:"+intBuffer.limit());
  }

输出结果如下

limit:5
postion:2
调用flip方法后
postion:0
limit:2

当往Buffer对象里写入数据后,接着想从Buffer对象读取数据时,程序如何知道最多能从Buffer对象里读取多少数据呢?这正是limit属性被引入的目的。也是读取数据时,为什么要先调用filp方法的原因。

本文标签: bufferNIONettylimitCapacity