美文网首页
Java NIO读书笔记 -- (四) 缓冲区创建

Java NIO读书笔记 -- (四) 缓冲区创建

作者: 我的小鱼干去哪儿了 | 来源:发表于2017-08-17 20:55 被阅读0次

    缓冲区的创建

    1. 有七种主要的缓冲区类,每一种都具有一种Java语言中的非布尔类型的原始类型数据。
    2. 第8种缓冲区类为MappedByteBuffer, 是ByteBuffer 专门用来内存映射文件的一种特例
    3. 这些缓冲区类是抽象类,都不能直接实例化,需要使用包含的静态工厂方法来创建相应类的实例。

    七种缓冲区类分别是 CharBuffer, IntBuffer, DoubleBuffer, ShortBuffer, LongBuffer, FloatBuffer, ByteBuffer。

    缓冲区创建的关键函数

    以下的关键函数对所有缓冲区类通用(只需替换类名)

    public abstract class CharBuffer extends Buffer implements CharSequence, Comparable {
         // This is a partial API listing 
        public static CharBuffer allocate (int capacity)   
        public static CharBuffer wrap (char [] array) 
        public static CharBuffer wrap (char [] array, int offset, int length) 
        public final boolean hasArray( ) 
        public final char [] array( ) 
        public final int arrayOffset( )
    }
    

    新的缓冲区是由分配或包装操作创建

    • 分配操作创建一个缓冲区对象并分配一个私有的空间来储存容量大小的数据元素。
    • 包装操作创建一个缓冲区对象但是不分配任何空间来储存数据元素。它使用您提供的数组作为存储空间来储存缓冲区中的数据元素。

    1. 分配创建

    分配一个容量为100个char变量的CharBuffer:

    CharBuffer charBuffer = CharBuffer.allocate(100);
    

    这段代码从堆空间中分配了一个char型数组作为备份存储器来储存100个char变量。

    2. 包装创建

    ①用自己的数组做缓冲区的备用存储器:

    char[] myArray = new char[100];
    CharBuffer charBuffer = CharBuffer.wrap(myArray);
    

    构造了一个新的缓冲区对象,但数据元素会存在于数组中。这意味着通过调用 put()函数造成的对缓冲区的改动会直接影响这个数组,而且对这个数组的任何改动也会对这 个缓冲区对象可见。

    ②带有 offset 和 length 作为参数的 wrap()函数版本则会构造一个按照您提供的 offset 和 length 参数值初始化位置和上界的缓冲区

    CharBuffer charBuffer = CharBuffer.wrap(myArray, 12, 42);
    

    创建了一个 position 值为 12,limit 值为 54,容量为 myArray.length 的缓冲区。

    ③这个函数并不像您可能认为的那样,创建了一个只占用了一个数组子集的缓冲区。

    这个缓冲区可以存取这个数组的全部范围;offset 和 length 参数只是设置了初始的状态。调用使用上面代码中的方法创建的缓冲区中的 clear()函数, 然后对其进行填充, 直到超过上界值,这将会重写数组中的所有元素。Slice()函数可以提供一个只占用备份数组一部分的缓冲区。

    3. 获取备用数组

    通过 allocate()或者 wrap()函数创建的缓冲区通常都是间接的。间接的缓冲区使用备份数组,您可以通过上面列出的 API 函数获得对这些数组的存取权。Boolean 型函数 hasArray()告诉您这个缓冲区是否有 一个可存取的备份数组。如果这个函数的返回 true,array()函数会返回这个缓冲区对象所 使用的数组存储空间的引用。

    4. 只读缓冲区

    如果 hasArray()函数返回 false,不要调用 array()函数或者 arrayOffset()函 数。如果您这样做了您会得到一个 UnsupportedOperationException 异常。如果一个缓冲区是只读的,它的备份数组将会是超出上界的,即使一个数组对象被提供给 wrap()函数。 调用 array()函数或者 arrayOffset()会抛出一个 ReadOnlyBufferException 异常, 来阻止您得到存取权来修改只读缓冲区的内容。如果您通过其它的方式获得了对备份数组的存 取权限, 对这个数组的修改也会直接影响到这个只读缓冲区。

    5. arrayOffset()函数

    ① arrayOffset(), 返回缓冲区数据在数组中存储的开始位置的的偏移量 (从数组头 0 开始计算)。

    如果您使用了带有三个参数的版本的 wrap()函数来创建一个缓冲 区,对于这个缓冲区,arrayOffset()会一直返回 0。

    ② 如果您切分了由一个数组提供存储的缓冲区,得到的缓冲区可能会有一个非 0 的数组偏移量。

    这个数组偏移量和缓冲区容量值会告诉您数组中哪些元素是被缓冲区使用的。

    6. CharBuffer 独特的便捷创建函数

    public abstract class CharBuffer extends Buffer implements CharSequence, Comparable {
        // This is a partial API listing
        public static CharBuffer wrap (CharSequence csq) 
        public static CharBuffer wrap (CharSequence csq, int start, int end)
    }
    

    wrap()函数创建一个只读的备份存储区是 CharSequence 接口或者其实现的的缓冲区 对象。

    Wrap()函数可以很实用地"缓冲"一个已有的字符数据, 通过缓冲区的 API 来存取其中的内容。

    三个参数的 wrap()函数版本使用 start 和 end 下标参数来描述传入的 CharSequence 对象的子序列。 这是一个方便的类似于调用了 CharSequence.subsequence()函数的转 换。Start 参数是序列中使用的第一个字符,end 是最后一个字符的下标值加 1。
    其中position = start, limit = end , capacity = csq.length()

    相关文章

      网友评论

          本文标题:Java NIO读书笔记 -- (四) 缓冲区创建

          本文链接:https://www.haomeiwen.com/subject/xjinrxtx.html