创建缓冲区的方式

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

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》

Java NIO中的缓冲区Buffer(二)创建/复制缓冲区的更多相关文章

  1. Java NIO中的缓冲区Buffer(一)缓冲区基础

    什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...

  2. java NIO中的buffer和channel

    缓冲区(Buffer):一,在 Java NIO 中负责数据的存取.缓冲区就是数组.用于存储不同数据类型的数据 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区:ByteBufferC ...

  3. Java NIO中的Buffer 详解

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  4. Java NIO中核心组成和IO区别

    1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...

  5. java输入输出 -- java NIO之缓存区Buffer

    一.简介 java NIO相关类在jdk1.4被引入,用于提高I/O的效率.java NIO包含很多东西,但核心的东西不外乎Buffer.channel和selector.本文先来看Buffer的实现 ...

  6. Java NIO学习-详细内容(二)

    五.Selector与SelectionKey Selector是SelectableChannel 对象的多路复用器,为什么使用Selector? 仅用单个线程来处理多个Channels的好处是,只 ...

  7. 转:Java NIO系列教程(三) Buffer

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  8. Java NIO(三) Buffer

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  9. 转载Java NIO中的Files类的使用

    Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法. Files.exists() Files.exits()方法用来检查给定的Path在文件 ...

随机推荐

  1. 正则RegExp的懒惰性和贪婪性; 分组捕获;

    1.正则的懒惰性??? 每次在它的方法exec中捕获的时候,只捕获第一次匹配的内容,而不往下捕获,我们把这种情况称为正则的懒惰性 且每一次捕获的位置都是从索引0开始 正则的实例对象上有一个lastin ...

  2. Android 获得本地IP地址、外网IP地址、本设备网络状态信息、本地Mac地址

    本地内网IP和外网IP的区别: 根据我的经验一台电脑需要两个ip才可以上网,一个是本地的内网ip 一个是外网的ip 本地的ip 一般是192.168.1.2这种样子  只要在不同的路由器上可以重复 外 ...

  3. [Python] Window机器上同时安装Python 2 和 Python 3,如何兼容切换使用?

    不论python2还是python3,python可执行文件都叫python.exe,在cmd下输入python得到的版本号取决于环境变量里哪个版本的python路径更靠前. 切换的方法有3种(方法3 ...

  4. atom编辑器使用“apm install”无法响应的解决方案

    工具:shadowsocks 利用ss建立代理服务,之后apm --help,得到apm的配置命令: apm - Atom Package Manager powered by https://ato ...

  5. vim折叠设置(转载)

    vim折叠设置(转载) set foldmethod=indent "set default foldmethod"zi 打开关闭折叠"zv 查看此行zm 关闭折叠zM ...

  6. 延迟执行(Invoke 函数)和消息发送(SendMessage 函数)

    Invoke 函数需要继承 MonoBehaviour 类后才能使用. Invoke(string str,float a):a 秒后执行名为 str 函数(只会调用一次). Invoke(strin ...

  7. 在windows 下使用eclipse进行编译和烧写

    eclipse IDE是一款开源的前端编程软件,它提供了编写,编译和调试ESP-IDF项目的图形集成开发环境. 首先在https://www.obeo.fr/en/eclipse-download?I ...

  8. bash编程-Shell变量

    bash中,所有变量的值默认均为字符串. 1. 变量操作 调用变量 $变量 查看变量(所有类型) set 删除变量 unset 变量 2. 变量分类 2.1 自定义变量 自定义变量仅对当前Shell有 ...

  9. 开源播放器 ijkplayer (一) :使用Ijkplayer播放直播视频

    1.ijkplayer 编码 IjkPlayer支持硬解码和软解码. 软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_R ...

  10. js验证身份证号,超准确

    js验证身份证号,超准确 看程序前先来了解下身份证号的构成:身份证号分为两种,旧的为15位,新的为18位.身份证15位编码规则:dddddd yymmdd xx p    其中 dddddd:地区码  ...