java nio buffer 通过 position 和 limit 配合 flip()、clear()、compact() 实现读写切换:写后用 flip() 设 limit=position、position=0 进入读模式;读完用 clear() 重置 position=0、limit=capacity 准备再写;部分读后用 compact() 移动未读数据至开头并更新 position。

Java NIO 中 Buffer 本身没有“读模式”或“写模式”的显式开关,它的读写切换本质是通过 position 和 limit 的配合,以及调用 flip()、clear()、compact() 等关键方法来完成的。核心在于理解 Buffer 的四个关键索引(mark、position、limit、capacity)及其状态流转。
写入后准备读取:用 flip() 切换到读模式
向 Buffer 写入数据(如调用 put())后,position 会移动到写入末尾,此时不能直接读——因为 limit 还在容量末端,而有效数据只到当前 position。必须调用 buffer.flip():
-
limit被设为当前position(即有效数据长度) -
position重置为 0 -
mark被丢弃(设为 -1)
之后调用 get() 就能从头开始读取有效数据,直到 position == limit。
读取完成后准备再次写入:用 clear() 重置为写模式
读完所有数据(position == limit)后,若要复用该 Buffer 写入新内容,调用 buffer.clear():
-
position设为 0 -
limit设为capacity -
mark被丢弃
注意:clear() 不清空数据,只是重置指针——旧数据仍保留在数组中,后续 put() 会覆盖。这是高效复用的关键。
部分读取后还想继续写入:用 compact() 压缩剩余数据
如果只读了一部分(position ),但 Buffer 中还有未读数据,又想追加新内容,直接 <code>clear() 会丢失未读数据。此时应调用 buffer.compact():
- 将未读数据(
position到limit)复制到 Buffer 起始位置 -
position设为已复制的数据长度 -
limit设为capacity
这样既保留了残留数据,又腾出尾部空间供新写入,适合循环读写场景(如网络分包处理)。
小技巧:避免手动调错顺序
常见错误是写完不 flip() 就读,或读完不 clear() 就再写。建议养成固定流程习惯:
- 写 →
flip()→ 读 →clear()(全读完) 或compact()(部分读) - 使用
hasRemaining()判断是否还有可读/可写空间,比手动比较position和limit更安全 - 调试时可用
toString()(如ByteBuffer的默认实现)快速查看当前 position/limit/capacity 状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











