flip()将position赋给limit并重置position为0,实现写→读切换;clear()将position设为0、limit设为capacity,实现读→写复用;二者均不擦除数据,仅重置指针。
掌握 buffer 的 flip 与 clear 切换逻辑,关键在于理解 position、limit 和 capacity 三者如何协同控制读写边界,而不是死记方法行为。它们共同构成一个“状态机”,flip 和 clear 只是这个状态机的两种标准切换动作。
flip():从写完到准备读的核心一步
当你调用 put() 写入数据后,position 会随写入字节数递增,limit 仍等于 capacity(表示整个缓冲区都可写)。此时若直接 get() 或 write() 到通道,读取范围是 [position, limit),即空区域——什么也读不到。
flip() 做且只做两件事:
- 把当前 position 的值赋给 limit(标记“有效数据到此为止”)
- 把 position 重置为 0(准备好从头读)
例如:容量为 10 的 ByteBuffer,写入 "Hi"(2 字节)后,position=2,limit=10;flip() 后,limit=2,position=0。后续 get() 就能依次读出 'H'、'i',读完时 position=2,等于 limit,hasRemaining() 返回 false。
clear():读完后重置为可写状态
当数据已全部读取完毕(position == limit),你想复用这个 Buffer 接收新数据,就该调用 clear()。
它恢复的是“初始写模式”的指针状态:
- position 设为 0
- limit 设回 capacity
注意:clear() 不擦除内存内容,只是重置指针——旧数据还在数组里,但下次 put() 会从索引 0 开始覆盖。这是高效复用的设计,不是清零操作。
别混淆 rewind() 和 clear()
rewind() 只重置 position=0,limit 不变。它适用于“想重读一遍刚写入的数据”,但不适用于准备下一轮写入——因为 limit 还卡在上次 flip 后的有效长度,put() 只能在 [0, limit) 范围内写,容易越界或写不满。
而 clear() 是真正为下一次 channel.read(buffer) 或 buffer.put(...) 准备的完整重置动作。
典型使用链:写 → flip → 读 → clear → 循环
这是 NIO 文件或网络读写的主干流程:
- 分配 buffer = ByteBuffer.allocate(1024)
- channel.read(buffer) → 自动写入,position 增加
- buffer.flip() → 切换为读模式
- while (buffer.hasRemaining()) process(buffer.get()) → 消费数据
- buffer.clear() → 指针归位,等待下一次 read()
漏掉 flip(),读不到数据;漏掉 clear(),下一次 read() 会因 position > 0 导致写入空间不足甚至抛出异常。










