三、ByteBuffer详解

1.ByteBuffer 的设计是抽象类

主要的实现类有:

HeapByteBuffer 堆 ByteBuffer 用的是 JVM 内的堆内存 --> 读写操作效率低 会受到 GC 的影响
2. MapperByteBuffer（抽象类 ，它还有个实现类叫 DirectByBuffer） 使用 OS 内存 ---> 读写操作效率高 不受 GC 影响。但是如果不主动析构的话，容易造成内陆泄露

获取方式

Bytebuffer.allocate (10); // 一旦分配空间，不可以动态调整
encode()

核心结构

ByteBuffer 是一个类似数组的结构，整个结构中包含三个主要的状态

Capacity
buffer 的容量，类似于数组的 size

Position
buffer 当前缓存的下标，在读取操作时记录读到了那个位置，在写操作时记录写到 > 了那个位置。从 0 开始，每读取一次，下标 + 1

Limit
读写限制，在读操作时，设置了你能读多少字节的数据，在写操作时，设置了你
还能写多少字节的数据
所谓的读写模式，本质上就是这几个状态的变化。主要有 Position 和 Limit 联合决定了 Buffer 的读写数据区域。

** 下面用图和代码的形式来表达 capacity、limit 、position 的状态改变 **

Copy
@Test
public void test1(){

ByteBuffer buffer = ByteBuffer.allocate(10);

// 新创建的buffer 的状态
System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 0
System.out.println("buffer.limit() = " + buffer.limit()); // 10

}

Copy
@Test
public void test2(){

ByteBuffer buffer = ByteBuffer.allocate(10);

// 存几个数据，然后再看状态
buffer.put(new byte[]{'a','b','c','d'});

System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 4
System.out.println("buffer.limit() = " + buffer.limit()); // 10

}

Copy
@Test
public void test3(){

ByteBuffer buffer = ByteBuffer.allocate(10);

// 存几个数据
buffer.put(new byte[]{'a','b','c','d'});

// 切换为读模式，再看状态
buffer.flip();

System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 0
System.out.println("buffer.limit() = " + buffer.limit()); // 4

}

Copy
@Test
public void test4(){

ByteBuffer buffer = ByteBuffer.allocate(10);

// 存几个数据
buffer.put(new byte[]{'a','b','c','d'});

// 切换为写模式，再看状态
buffer.clear();

System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 0
System.out.println("buffer.limit() = " + buffer.limit()); // 10

}

Copy
@Test
public void test5(){

ByteBuffer buffer = ByteBuffer.allocate(10);

// 存几个数据
buffer.put(new byte[]{'a','b','c','d'});

// 读取2个数据
buffer.flip();
byte b = buffer.get();
byte b2 = buffer.get();

System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 2
System.out.println("buffer.limit() = " + buffer.limit()); // 4

// 用compact来切换写模式，再看状态
buffer.compact();

System.out.println("buffer.capacity() = " + buffer.capacity()); // 10
System.out.println("buffer.position() = " + buffer.position()); // 2
System.out.println("buffer.limit() = " + buffer.limit()); // 10
/* 结果
* buffer.capacity() = 10
buffer.position() = 2
buffer.limit() = 4
buffer.capacity() = 10
buffer.position() = 2
buffer.limit() = 10
* */
}

最后总结一下

写入 Buffer 数据之前要设置写模式

写模式

新创建的 Buffer 自动是写模式

调用了 clear,compact 方法

读取 Buffer 数据之前要设置读模式
2. 读模式

调用 flip 方法