一、Buffer
首先可以看到Buffer的一个层级。Object-Buffer-{ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer}。
源码这里给出了Buffer的定义——Buffer是一个基本数据类型的元素组成的列表。下面列出它的属性:
- Capacity:Buffer可以容纳的元素个数,非负数并且不可变。
- Position:Buffer的游标,通过它可以读写元素,非负数并且不得超过Limit。
- Limit:控制可获取的元素范围,你只能读或写0~limit-1范围的元素。超过范围将抛出异常。Limit不为负数并且不超过Capacity
- Mart:用于记录当前的Postion。
一个Buffer有两种:只读、读写。当你尝试修改只读的buffer的元素时将抛出ReadOnlyBufferException。
一个Buffer有两种:直接、间接。直接型的buffer使用Native函数库分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。因此虽然直接缓存区是堆外内存,但当DirectByteBuffer被GC回收时,堆外内存依然会被释放掉。
Buffer不是线程安全的,所以在并发多线程中应该考虑线程安全问题。
这里要提到一个抽象方法array。
public abstract Object array();
该方法返回支持buffer的数组。这个数组是一个真实的数组,而非copy来的,对数组的修改将写入buffer。继承Buffer的子类应该override该方法。
二、ByteBuffer
让我们看下ByteBuffer的创建方式:
- allocate(int capacity) 一个新的字节数组,并且创建基于它的缓存(ByteArrayBuffer)。
- allocateDirect(int capacity)一个内存块,并且创建基于它的直接缓存(DirectByteBuffer,GC无法回收)。
- wrap(byte[] wrap) 使用一个已经存在的字节数组创建一个新的缓存(ByteArrayBuffer)。
字节是其他数据类型(short-2byte;int-4byte;long-8byte;float-4byte;double-8byte;char-2byte)的基础,因此可以将这些基本数据类型的数据写入字节缓存区或者读出。可以使用它提供的方法,诸如getChar()、getInt()、putFloat()、putInt().....
三、CharBuffer
看一下CharBuffer的创建方式:
- allocate(int capacity)创建一个新的字符数组,并且对应一个缓存(CharArrayBuffer)。
- wrap(char[] array)基于已存在的字符数组,创建一个新的缓存
- warp(CharSequence c)基于已存在的CharSequence,创建一个新的缓存
四、DoubleBuffer
看一下DoubleBuffer的创建方式
- allocate(int capacity)创建一个新的double数组,并且创建对应一个缓存(DoubleArrayBuffer)
- wrap(double[] array)基于已存在的double数组,创建一个新的缓存
FloatBuffer、IntBuffer、LongBuffer、ShortBuffer都与以上类似。利用这些Buffer,可以把数据写到对应的缓存里面,也可以读出来。