创建缓冲区的方式

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

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. 关于TP5.0搜索后分页

    使用$Model->where($where)->paginate($page,$count);的时候如果点击下一页会出现条件重置问题,经过测试可以使用Db::name('data') - ...

  2. 258. Add Digits 入学考试:数位相加

    [抄题]: Given a non-negative integer num, repeatedly add all its digits until the result has only one ...

  3. 记录一次Centos磁盘空间占满的解决办法(转)

    原文地址:https://blog.csdn.net/everything1209/article/details/70209157 解决前 磁盘使用情况: 第二块磁盘使用率达到97% [root@f ...

  4. Quartz.NET快速入门指南

    最近,在工作中遇到了 Quartz.net 这个组件,为了更好的理解项目代码的来龙去脉,于是决定好好的研究一下这个东西.确实是好东西,既然是好东西,我就拿出来分享一下.万丈高楼平地起,我们也从入门开始 ...

  5. swap的实现(没有中间变量)

    两数交换最常用的方法 void swap(int &a,int &b) { int temp=a; a=b; b=temp; } 如果没有中间变量temp可以使用呢,还有其他的三种方法 ...

  6. 查看memcached进程

  7. List,set,Map理解

    集合 集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...

  8. 2019.02.12 bzoj3944: Sum(杜教筛)

    传送门 题意: 思路:直接上杜教筛. 知道怎么推导就很简单了,注意预处理的范围. 然后我因为预处理范围不对被zxyoi教育了(ldx你这个傻×两倍常数活该被卡TLE) 喜闻乐见 代码: #includ ...

  9. IDEA中MyBaits的Mapper文件颜色问题

    IDEA中MyBaits的Mapper文件颜色问题 在IDEA中Mapper文件的展示 包含的警告及其解决方案 然后我们就完成了,效果如下 在IDEA中Mapper文件的展示 在IDEA中,Mappe ...

  10. HDU 2639 01背包(分解)

    http://acm.hdu.edu.cn/showproblem.php?pid=2639 01背包第k优解,把每次的max分步列出来即可 #include<stdio.h> #incl ...