Java NIO中的缓冲区Buffer(二)创建/复制缓冲区

创建缓冲区的方式

主要有以下两种方式创建缓冲区:

1、调用allocate方法

2、调用wrap方法

我们将以charBuffer为例,阐述各个方法的含义;

allocate方法创建缓冲区

调用allocate方法实际上会返回new HeapCharBuffer(capacity, capacity)对象;

缓存空间存储在CharBuffer类的成员属性char[] hb数组里,即JVM堆里;

如下示例,创建了一个容量大小为10的CharBuffer:

CharBuffer bf = CharBuffer.allocate(10);

allocate方法其实比较简单,不过有点需要注意的是,allocate方法除了可以分配JVM堆空间,还可以分配直接内存空间(如ByteBuffer,可以调用allocateDirect方法分配直接内存),其内部是通过调用unsafe.allocateMemory方法实现直接内存分配的,该空间不在JVM堆内部,后续会做更加详细的说明;不过可以稍微提醒一点,如果是直接内存空间的话,调用hasArray()方法会返回false;

wrap方法创建缓冲区

调用wrap方法实际上会也会返回new HeapCharBuffer(array, offset, length)对象;

与allocate方法的区别是,它的缓存存储空间是外部传入的;

如下示例,创建了一个容量大小为10的CharBuffer:

        char[] myArray = new char[10];
        CharBuffer charbuffer = CharBuffer.wrap(myArray);

另外,wrap还有一个重载方法:带offset和length作为参数的wrap()方法,如下是该方法的一个示例:

        char[] myArray = new char[10];
        CharBuffer charbuffer = CharBuffer.wrap (myArray, 2, 3);

以上代码将会创建一个position = 2, limit = 5, capacity = 10的Buffer;

复制缓冲区的方式

主要有以下三种方式复制缓冲区:

1、调用duplicate方法

2、调用asReadOnlyBuffer方法

3、调用slice方法

我们将以charBuffer为例,阐述各个方法的含义;

duplicate方法复制缓冲区

调用duplicate方法实际上会创建原缓存区的一个拷贝,不是深拷贝,是浅拷贝,什么意思呢,就是这两个缓存区会共享数据元素,但每个缓存区的上界、容量、位置等属性是各自独立的;

修改其中一个缓存区的元素会影响另一个拷贝缓存区,如下示例:

        CharBuffer charbuffer1 = CharBuffer.allocate(10);
        CharBuffer charbuffer2 = charbuffer1.duplicate();

        charbuffer1.put('a').put('b').put('c');
        charbuffer1.flip();

        System.out.println(charbuffer1);
        System.out.println(charbuffer2);

charbuffer2缓存区复制了charbuffer1缓存区,至始至终我们只操作charbuffer1缓存区,最后打印的时候,却发现charbuffer2缓存区里已经有了charbuffer1缓存区的数据,结果打印如下:

abc
abc

asReadOnlyBuffer方法复制缓冲区

调用asReadOnlyBuffer方法会生成一个只读缓存区,与调用duplicate方法基本一致,唯一的区别是这个缓存区是只读的,若对其进行put操作的话,会抛出ReadOnlyBufferException;

如下示例:

        CharBuffer charbuffer1 = CharBuffer.allocate(10);
        CharBuffer charbuffer2 = charbuffer1.asReadOnlyBuffer();

        charbuffer1.put('a').put('b').put('c');
        charbuffer1.flip();

        System.out.println(charbuffer1);
        System.out.println(charbuffer2);

        charbuffer2.put('c');//ReadOnlyBufferException

输出结果:

abc
abc
Exception in thread "main" java.nio.ReadOnlyBufferException
    at java.nio.HeapCharBufferR.put(HeapCharBufferR.java:166)
    at nio.Main.main(Main.java:21)

slice方法复制缓冲区

slice方法其实是用于分割缓存区的,该方法创建了一个从原始缓冲区的当前位置开始的新缓冲区,并且其容量是原始缓冲区的剩余元素数量(limit-position);

该缓存区与原始缓存区共享一段序列;

如下示例:

1、我们先创建一个容量为10的缓存区charbuffer1

CharBuffer charbuffer1 = CharBuffer.allocate(10);

此时:mark = -1; position = 0; limit = 10; capacity = 10;

2、修改charbuffer1的position和limit值

charbuffer1.position(2).limit(5);

此时:mark = -1; position = 2; limit = 5; capacity = 10;

3、调用slice方法,对charbuffer1缓存区进行分割

CharBuffer charbuffer2 = charbuffer1.slice();

此时:

charbuffer1:mark = -1; position = 2; limit = 5; capacity = 10;

charbuffer2:mark = -1; position = 0; limit = 3; capacity = 3;

 

 参考资料

《Java NIO》

posted @ 2017-02-28 14:37  风一样的码农  阅读(5968)  评论(0编辑  收藏  举报