zoukankan      html  css  js  c++  java
  • 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》

  • 相关阅读:
    vue element-ui配置第三方图标库
    HTTP协议:状态码
    HTTP协议:无状态
    CDN:基础知识
    【转载】浅析机器视觉中的照明系统(该如何打光)
    nginx 端口转发
    Gitlab 备份 | 恢复 | 卸载 | 迁移 | 版本升级
    微信小程序支付服务端.net core实现,简单直接
    生产级gitlab备份
    背锅之旅:前任对我的爱-只备份不删除导致的磁盘爆满
  • 原文地址:https://www.cnblogs.com/chenpi/p/6478624.html
Copyright © 2011-2022 走看看