为什么要讲 Buffer
首先为什么一个小小的 Buffer 我们需要单独拎出来聊?或者说,Buffer 具体是在哪些地方被用到的呢?
例如,我们从磁盘上读取一个文件,并不是直接就从磁盘加载到内存中,而是首先会将磁盘中的数据复制到内核缓冲区中,然后再将数据从内核缓冲区复制到用户缓冲区内,在图里看起来就是这样:

再比如,我们往磁盘上写文件,也不是直接将数据写到磁盘。而是将数据从用户缓冲区写到内核缓冲区,由操作系统择机将其刷入磁盘,图跟上面这个差不多,就不画了,自行理解。
再再比如,服务器接受客户端发过来的数据时,也不是直接到用户态的 Buffer 中。而是会先从网卡到内核态的 Buffer 中,再从内核态的 Buffer 中复制到用户态的 Buffer 中。
那为什么要这么麻烦呢?复制来复制去的,首先我们用排除法排除这样做是为了好玩。
Buffer 存在的目的是为了减少与设备(例如磁盘)的交互频率,在之前的博客中也提到过「磁盘的读写是很昂贵的操作」。那昂贵在哪里呢?简单来说,和设备的交互(例如和磁盘的IO)会设计到操作系统的中断。中断需要保存之前的进程运行的上下文,中断结束之后又需要恢复这个上下文,并且还涉及到内核态和用户态的切换,总体上是个耗时的操作。
看到这里,不熟悉操作系统的话可能会有点疑惑。例如:
-
啥是用户态 -
啥是内核态
大家可以去看看我之前写的文章 《简单聊聊用户态和内核态的区别》
Buffer 的使用
我们通过 Java 中 NIO 包中实现的 Buffer 来给大家讲解,Buffer 总共有 7 种实现,就包含了 Java 中实现的所有数据类型。

本篇文章中,我们使用的是 ByteBuffer,其常用的方法都有:
-
put -
get -
flip -
rewind -
mark -
reset -
clear
接下来我们就通过实际的例子来了解这些方法。
put
put
就是往 ByteBuffer 里写入数据,其有有很多重载的实现:
1 2 3 4 5 6 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> ByteBuffer <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">put</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(ByteBuffer src)</span> </span>{...} <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> ByteBuffer <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">put</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[] src, <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> offset, <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> length)</span> </span>{...} <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">final</span> ByteBuffer <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">put</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[] src)</span> </span>{...} </code></span> |
我们可以直接传入 ByteBuffer
对象,也可以直接传入原生的 byte
数组,还可以指定写入的 offset 和长度等等。接下来看个具体的例子:
1 2 3 4 5 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>,<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); } </code></span> |
为了能让大家更直观的看出 ByteBuffer 内部的情况,我将它整理成了图的形式。当上面的代码运行完之后 buffer
的内部长这样:

当你尝试使用 System.out.println(buffer)
去打印变量 buffer
的时候,你会看到这样的结果:
1 2 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;">java.nio.HeapByteBuffer[pos=2 lim=16 <span class="hljs-built_in" style="color: rgba(92, 38, 153, 1); line-height: 26px;">cap</span>=16] </code></span> |
图里、控制台里都有 position
和 limit
变量,capacity
大家能理解,就是我们创建这个 ByteBuffer 的制定的大小 16
。
而至于另外两个变量,相信大家从图中也可以看出来,position
变量指向的是下一次要写入的下标,上面的代码我们只写入了 2 个字节,所以 position
指向的是 2,而这个 limit
就比较有意思了,这个在后面的使用中结合例子一起讲。
get
get
是从 ByteBuffer 中获取数据。
1 2 3 4 5 6 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>,<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); System.out.println(buffer.get()); } </code></span> |
如果你运行完上面的代码你会发现,打印出来的结果是 0
,并不是我们期望的 s
的 ASCII 码 115
。
首先告诉大家结论,这是符合预期的,这个时候就不应该能获取到值。我们来看看 get
的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">get</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">()</span> </span>{ <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">return</span> hb[ix(nextGetIndex())]; } <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">protected</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">ix</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> i)</span> </span>{ <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">return</span> i + offset; } <span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">final</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">nextGetIndex</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">()</span> </span>{ <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">int</span> p = position; <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">if</span> (p >= limit) <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">throw</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> BufferUnderflowException(); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// 这里 position 会往后移动一位</span> position = p + <span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">1</span>; <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">return</span> p; } </code></span> |
当前 position
是 2,而 limit
是 16,所以最终 nextGetIndex
计算出来的值就是变量 p
的值 2 ,再过一次 ix
,那就是 2 + 0 = 2
,这里的 offset
的值默认为 0 。
所以简单来说,最终会取到下标为 2 的数据,也就是下图这样。

所以我们当然获取不到数据。但是这里需要关注的是,调用 get
方法虽然没有获取到任何数据,但是会使得 position
指针往后移动。换句话说,会占用一个位置。如果连续调用几次这种 get
之后,再调用 put
方法写入数据,就会造成有几个位置没有赋值。举个例子,假设我们运行以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>,<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); buffer.get(); buffer.get(); buffer.get(); buffer.get(); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'e'</span>}); } </code></span> |
数据就会变成下图这样,position
会往后移动

那你可能会问,那我真的需要获取数据咋办?在这种情况下,可以像这样获取:
1 2 3 4 5 6 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>}); System.out.println(buffer.get(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">0</span>)); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// 115</span> } </code></span> |
传入我们想要获取的下标,就可以直接获取到,并且不会造成 position
的后移。
看到这那你更懵逼了,合着 get()
就没法用呗?还必须要给个 index。这就需要聊一下另一个方法 flip
了。
flip
废话不多说,先看看例子:
1 2 3 4 5 6 7 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>, <span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// java.nio.HeapByteBuffer[pos=2 lim=16 cap=16]</span> buffer.flip(); System.out.println(buffer); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// java.nio.HeapByteBuffer[pos=0 lim=2 cap=16]</span> } </code></span> |
有意思的事情发生了,调用了 flip
之后,position
从 2 变成了 0,limit
从 16 变成了 2。
这个单词是「翻动」的意思,我个人的理解是像翻东西一样把之前存的东西全部翻一遍
你会发现,position
变成了 0,而 limit
变成 2,这个范围刚好是有值的区间。
接下来就更有意思了:
1 2 3 4 5 6 7 8 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>, <span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); buffer.flip(); System.out.println((<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">char</span>)buffer.get()); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// s</span> System.out.println((<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">char</span>)buffer.get()); <span class="hljs-comment" style="color: rgba(0, 116, 0, 1); line-height: 26px;">// h</span> } </code></span> |
调用了 flip
之后,之前没法用的 get()
居然能用了。结合 get
中给的源码不难分析出来,由于 position
变成了 0,最终计算出来的结果就是 0,同时使 position
向后移动一位。
终于到这了,你可以理解成 Buffer 有两种状态,分别是:
-
读模式 -
写模式
刚刚创建出来的 ByteBuffer 就处于一个写模式的状态,通过调用 flip
我们可以将 ByteBuffer 切换成读模式。但需要注意,这里讲的读、写模式只是一个逻辑上的概念。
举个例子,当调用 flip
切换到所谓的写模式之后,依然能够调用 put
方法向 ByteBuffer 中写入数据。
1 2 3 4 5 6 7 |
<span style="display: block; background: url('https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg') 10px 10px / 40px no-repeat rgba(255, 255, 255, 1); height: 30px; width: 100%; margin-bottom: -7px; border-radius: 5px;"><code class="hljs" style="overflow-x: auto; padding: 15px 16px 16px; color: rgba(0, 0, 0, 1); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; background: rgba(255, 255, 255, 1); border-radius: 5px;"><span class="hljs-function" style="line-height: 26px;"><span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">public</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">static</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">void</span> <span class="hljs-title" style="color: rgba(28, 0, 207, 1); line-height: 26px;">main</span><span class="hljs-params" style="color: rgba(92, 38, 153, 1); line-height: 26px;">(String[] args)</span> </span>{ ByteBuffer buffer = ByteBuffer.allocate(<span class="hljs-number" style="color: rgba(28, 0, 207, 1); line-height: 26px;">16</span>); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'s'</span>, <span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'h'</span>}); buffer.flip(); buffer.put(<span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">new</span> <span class="hljs-keyword" style="color: rgba(170, 13, 145, 1); line-height: 26px;">byte</span>[]{<span class="hljs-string" style="color: rgba(196, 26, 22, 1); line-height: 26px;">'e'</span>}); } </code></span> |
这里的 put
操作依然能成功,但你会发现最后写入的 e
覆盖了之前的数据,现在 ByteBuffer 的值变成了 eh
而不是 sh
了。

所以你现在应该能够明白,读模式、写模式更多的含义应该是:
-
方便你读的